Pure CSS Cards & galleries #hover

Flip card in pure CSS

Hover, tap or focus to flip. The back face is hidden until it turns toward you.

  • 40 lines of CSS
  • 6 lines of HTML
  • No JavaScript
  • No dependencies
  • Snippet under MIT
GitHub

How it works

  1. Two faces share one box. The back one starts pre-rotated by rotateY(180deg).
  2. backface-visibility: hidden hides whichever face is pointing away from you.
  3. On :hover / :focus rotate the inner wrapper, not the hovered element — otherwise the hit area rotates away and flickers.
  4. tabindex="0" makes it work on touch and keyboard too.
  5. Every length is a multiple of one base unit, --u, so the card is the same share of a gallery card, the editor, a full screen and a recording canvas. Mid-turn the near half is magnified by the perspective, so the card is sized for the turn, not for the rest pose.

Key techniques

  • backface-visibility: hidden
  • transition
  • :hover / :focus

Copy-paste code

HTML 6 lines

<div class="flip" tabindex="0">
  <div class="flip-inner">
    <div class="flip-face">Front</div>
    <div class="flip-face flip-back">Back</div>
  </div>
</div>

CSS 40 lines

.flip {
  /* one base unit: every length below is a multiple of it, so the card is the same share of a
     card, the editor, a full screen and a recording canvas */
  --u: 0.34vmin;
  width: calc(240 * var(--u));
  height: calc(160 * var(--u));
  perspective: calc(800 * var(--u));
  cursor: pointer;
}

.flip-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.8s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.flip:hover .flip-inner,
.flip:focus .flip-inner {
  transform: rotateY(180deg);
}

.flip-face {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: calc(16 * var(--u));
  font: 700 calc(24 * var(--u)) Inter, system-ui;
  color: #fff;
  /* deep enough for white words (5.1:1 at the worst end): the bright #8b6cff to #ff4d9d was 3.3:1 */
  background: linear-gradient(135deg, #6a45f5, #d1206f);
  backface-visibility: hidden;
}

.flip-back {
  background: linear-gradient(135deg, #087a70, #6a45f5); /* deep for white words: #2ee6d6 was 1.6:1 */
  transform: rotateY(180deg);
}
Standalone snippet · plain CSS, no build step, no dependencies.