Pure TailwindMIT licensed

Tailwind Image Card Flip 3D Animation Hover

The three-layer flip — scene, flipper, two faces — with every one of its four critical properties now a named utility: [perspective:800px], transform-3d, backface-hidden and group-hover:rotate-y-180. The pattern's failure modes are all “you forgot one of these”, and a class list makes a missing one visible.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="tih-20 w-full min-h-svh grid place-items-center bg-tih20-bg font-tih20-sans px-6 py-10" aria-label="3D card flip hover demo">
  <div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
    <div class="group [perspective:800px] aspect-[3/4]">
      <div class="relative w-full h-full transform-3d transition-transform duration-650 ease-tih20 group-hover:rotate-y-180 focus-within:rotate-y-180 motion-reduce:transition-none motion-reduce:group-hover:rotate-y-0 motion-reduce:focus-within:rotate-y-0">
        <div class="absolute inset-0 flex flex-col justify-end overflow-hidden rounded-2xl backface-hidden bg-[image:url('https://picsum.photos/seed/tih20-cosmos/600/800'),linear-gradient(145deg,oklch(0.25_0.1_285),oklch(0.35_0.15_280),oklch(0.5_0.2_275),oklch(0.72_0.14_275))] bg-cover bg-center bg-no-repeat motion-reduce:opacity-100 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-0">
          <div class="relative z-1 p-4 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
            <p class="text-sm font-bold text-tih20-text">Cosmos Explorer</p>
            <p class="mt-0.5 text-[10px] text-tih20-muted">Astrophotography</p>
          </div>
          <span class="absolute top-2.5 right-2.5 z-2 px-2 py-0.75 rounded-full text-[9px] font-bold text-tih20-muted bg-[oklch(1_0_0/0.07)] border border-[oklch(1_0_0/0.1)] transition-opacity duration-300 group-hover:opacity-0">Hover to flip</span>
        </div>
        <div class="absolute inset-0 flex flex-col items-center justify-center p-5 overflow-hidden rounded-2xl backface-hidden rotate-y-180 bg-linear-[135deg,oklch(0.18_0.07_285),oklch(0.25_0.1_285)] motion-reduce:opacity-0 motion-reduce:rotate-y-0 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-100">
          <span class="mb-3 text-4xl" aria-hidden="true">&#127756;</span>
          <p class="mb-2 text-[15px] font-extrabold text-center text-tih20-text">20-Week Course</p>
          <p class="mb-3.5 text-[11px] leading-[1.5] text-center text-tih20-muted">Master astrophotography from light-pollution basics to deep-sky stacking.</p>
          <a href="#cosmos-enroll" class="px-4.5 py-2 rounded-full text-[11px] font-bold tracking-[0.05em] text-black no-underline bg-tih20-acc transition-[scale,box-shadow] duration-200 hover:scale-104 hover:shadow-[0_0_16px_oklch(0.8_0.14_163/0.4)] focus-visible:outline-2 focus-visible:outline-tih20-text focus-visible:outline-offset-2 motion-reduce:transition-none">Enroll Now</a>
        </div>
      </div>
    </div>
    <div class="group [perspective:800px] aspect-[3/4]">
      <div class="relative w-full h-full transform-3d transition-transform duration-650 ease-tih20 group-hover:rotate-y-180 focus-within:rotate-y-180 motion-reduce:transition-none motion-reduce:group-hover:rotate-y-0 motion-reduce:focus-within:rotate-y-0">
        <div class="absolute inset-0 flex flex-col justify-end overflow-hidden rounded-2xl backface-hidden bg-[image:url('https://picsum.photos/seed/tih20-bio/600/800'),linear-gradient(145deg,oklch(0.22_0.06_150),oklch(0.35_0.09_150),oklch(0.55_0.13_155),oklch(0.8_0.14_163))] bg-cover bg-center bg-no-repeat motion-reduce:opacity-100 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-0">
          <div class="relative z-1 p-4 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
            <p class="text-sm font-bold text-tih20-text">Bio Systems</p>
            <p class="mt-0.5 text-[10px] text-tih20-muted">Botany Research</p>
          </div>
          <span class="absolute top-2.5 right-2.5 z-2 px-2 py-0.75 rounded-full text-[9px] font-bold text-tih20-muted bg-[oklch(1_0_0/0.07)] border border-[oklch(1_0_0/0.1)] transition-opacity duration-300 group-hover:opacity-0">Hover to flip</span>
        </div>
        <div class="absolute inset-0 flex flex-col items-center justify-center p-5 overflow-hidden rounded-2xl backface-hidden rotate-y-180 bg-linear-[135deg,oklch(0.15_0.05_150),oklch(0.22_0.06_150)] motion-reduce:opacity-0 motion-reduce:rotate-y-0 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-100">
          <span class="mb-3 text-4xl" aria-hidden="true">&#129516;</span>
          <p class="mb-2 text-[15px] font-extrabold text-center text-tih20-text">Lab Access</p>
          <p class="mb-3.5 text-[11px] leading-[1.5] text-center text-tih20-muted">12 months of virtual lab sessions with live microscopy and specimen archives.</p>
          <a href="#bio-join" class="px-4.5 py-2 rounded-full text-[11px] font-bold tracking-[0.05em] text-black no-underline bg-tih20-acc transition-[scale,box-shadow] duration-200 hover:scale-104 hover:shadow-[0_0_16px_oklch(0.8_0.14_163/0.4)] focus-visible:outline-2 focus-visible:outline-tih20-text focus-visible:outline-offset-2 motion-reduce:transition-none">Join Lab</a>
        </div>
      </div>
    </div>
    <div class="group [perspective:800px] aspect-[3/4]">
      <div class="relative w-full h-full transform-3d transition-transform duration-650 ease-tih20 group-hover:rotate-y-180 focus-within:rotate-y-180 motion-reduce:transition-none motion-reduce:group-hover:rotate-y-0 motion-reduce:focus-within:rotate-y-0">
        <div class="absolute inset-0 flex flex-col justify-end overflow-hidden rounded-2xl backface-hidden bg-[image:url('https://picsum.photos/seed/tih20-arts/600/800'),linear-gradient(145deg,oklch(0.25_0.13_305),oklch(0.4_0.19_302),oklch(0.55_0.22_300),oklch(0.78_0.19_320))] bg-cover bg-center bg-no-repeat motion-reduce:opacity-100 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-0">
          <div class="relative z-1 p-4 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
            <p class="text-sm font-bold text-tih20-text">Digital Arts</p>
            <p class="mt-0.5 text-[10px] text-tih20-muted">Creative Studio</p>
          </div>
          <span class="absolute top-2.5 right-2.5 z-2 px-2 py-0.75 rounded-full text-[9px] font-bold text-tih20-muted bg-[oklch(1_0_0/0.07)] border border-[oklch(1_0_0/0.1)] transition-opacity duration-300 group-hover:opacity-0">Hover to flip</span>
        </div>
        <div class="absolute inset-0 flex flex-col items-center justify-center p-5 overflow-hidden rounded-2xl backface-hidden rotate-y-180 bg-linear-[135deg,oklch(0.17_0.09_310),oklch(0.25_0.13_305)] motion-reduce:opacity-0 motion-reduce:rotate-y-0 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-100">
          <span class="mb-3 text-4xl" aria-hidden="true">&#127912;</span>
          <p class="mb-2 text-[15px] font-extrabold text-center text-tih20-text">Creator Pack</p>
          <p class="mb-3.5 text-[11px] leading-[1.5] text-center text-tih20-muted">Unlimited generative art tools, 500+ premium assets and weekly critique sessions.</p>
          <a href="#arts-access" class="px-4.5 py-2 rounded-full text-[11px] font-bold tracking-[0.05em] text-black no-underline bg-tih20-acc2 transition-[scale,box-shadow] duration-200 hover:scale-104 hover:shadow-[0_0_16px_oklch(0.78_0.19_320/0.4)] focus-visible:outline-2 focus-visible:outline-tih20-text focus-visible:outline-offset-2 motion-reduce:transition-none">Get Access</a>
        </div>
      </div>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tih20-bg: #07070f;
  --color-tih20-bg: oklch(0.11 0.012 285);
  --color-tih20-text: #f1f5f9;
  --color-tih20-text: oklch(0.96 0.005 250);
  --color-tih20-muted: #64748b;
  --color-tih20-muted: oklch(0.68 0.03 255);
  --color-tih20-acc: #34d399;
  --color-tih20-acc: oklch(0.8 0.14 163);
  --color-tih20-acc2: #e879f9;
  --color-tih20-acc2: oklch(0.78 0.19 320);
  --font-tih20-sans: 'Space Grotesk', system-ui, sans-serif;
  --ease-tih20: cubic-bezier(0.45, 0, 0.55, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
   w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */

.tih-20 {
  width: 100%;
  min-height: 100svh;
}

.tih-20 ::selection {
  background: oklch(0.8 0.14 163);
  color: #000;
}
/* Firefox subpixel artefacts on face edges inside a 3D context. A bug workaround,
   which is exactly the category that should stay out of the markup. */

.tih-20 .backface-hidden {
  border: 1px solid transparent;
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tih20-bg: #07070f;
  --color-tih20-bg: oklch(0.11 0.012 285);
  --color-tih20-text: #f1f5f9;
  --color-tih20-text: oklch(0.96 0.005 250);
  --color-tih20-muted: #64748b;
  --color-tih20-muted: oklch(0.68 0.03 255);
  --color-tih20-acc: #34d399;
  --color-tih20-acc: oklch(0.8 0.14 163);
  --color-tih20-acc2: #e879f9;
  --color-tih20-acc2: oklch(0.78 0.19 320);
  --font-tih20-sans: 'Space Grotesk', system-ui, sans-serif;
  --ease-tih20: cubic-bezier(0.45, 0, 0.55, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
   w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */

.tih-20 {
  width: 100%;
  min-height: 100svh;
}

.tih-20 ::selection {
  background: oklch(0.8 0.14 163);
  color: #000;
}
/* Firefox subpixel artefacts on face edges inside a 3D context. A bug workaround,
   which is exactly the category that should stay out of the markup. */

.tih-20 .backface-hidden {
  border: 1px solid transparent;
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • All four of the pattern's load-bearing properties become utilities on the three elements that need them, so a missing one is visible in the markup rather than diagnosed from a broken flip.
  • backface-hidden emits the -webkit- prefix; the CSS version has to write both by hand on both faces.
  • rotate-y-180 appears twice with different meanings — statically on the back face, under group-hover: on the flipper — and reading them together is what makes the mechanism obvious.
  • focus-within:rotate-y-180 is added by the port. The back face holds the CTA, and in the CSS original that CTA is focusable while invisible.
  • motion-reduce: converts the flip into a cross-fade rather than merely disabling it, so the back content is still reachable without a 180° rotation.
  • The clip stays on the faces and never on the flipper — the one rule that makes 3D flips work, and the split is enforced by which element carries overflow-hidden.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Image Card Flip 3D Animation Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-image-card-flip-3d-animation-hover/

The three-layer flip &mdash; scene, flipper, two faces &mdash; with every one of its four critical properties now a named utility: [perspective:800px], transform-3d, backface-hidden and group-hover:rotate-y-180. The pattern's failure modes are all &ldquo;you forgot one of these&rdquo;, and a class list makes a missing one visible.
## HTML
```html
<section class="tih-20 w-full min-h-svh grid place-items-center bg-tih20-bg font-tih20-sans px-6 py-10" aria-label="3D card flip hover demo">
  <div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
    <div class="group [perspective:800px] aspect-[3/4]">
      <div class="relative w-full h-full transform-3d transition-transform duration-650 ease-tih20 group-hover:rotate-y-180 focus-within:rotate-y-180 motion-reduce:transition-none motion-reduce:group-hover:rotate-y-0 motion-reduce:focus-within:rotate-y-0">
        <div class="absolute inset-0 flex flex-col justify-end overflow-hidden rounded-2xl backface-hidden bg-[image:url('https://picsum.photos/seed/tih20-cosmos/600/800'),linear-gradient(145deg,oklch(0.25_0.1_285),oklch(0.35_0.15_280),oklch(0.5_0.2_275),oklch(0.72_0.14_275))] bg-cover bg-center bg-no-repeat motion-reduce:opacity-100 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-0">
          <div class="relative z-1 p-4 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
            <p class="text-sm font-bold text-tih20-text">Cosmos Explorer</p>
            <p class="mt-0.5 text-[10px] text-tih20-muted">Astrophotography</p>
          </div>
          <span class="absolute top-2.5 right-2.5 z-2 px-2 py-0.75 rounded-full text-[9px] font-bold text-tih20-muted bg-[oklch(1_0_0/0.07)] border border-[oklch(1_0_0/0.1)] transition-opacity duration-300 group-hover:opacity-0">Hover to flip</span>
        </div>
        <div class="absolute inset-0 flex flex-col items-center justify-center p-5 overflow-hidden rounded-2xl backface-hidden rotate-y-180 bg-linear-[135deg,oklch(0.18_0.07_285),oklch(0.25_0.1_285)] motion-reduce:opacity-0 motion-reduce:rotate-y-0 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-100">
          <span class="mb-3 text-4xl" aria-hidden="true">&#127756;</span>
          <p class="mb-2 text-[15px] font-extrabold text-center text-tih20-text">20-Week Course</p>
          <p class="mb-3.5 text-[11px] leading-[1.5] text-center text-tih20-muted">Master astrophotography from light-pollution basics to deep-sky stacking.</p>
          <a href="#cosmos-enroll" class="px-4.5 py-2 rounded-full text-[11px] font-bold tracking-[0.05em] text-black no-underline bg-tih20-acc transition-[scale,box-shadow] duration-200 hover:scale-104 hover:shadow-[0_0_16px_oklch(0.8_0.14_163/0.4)] focus-visible:outline-2 focus-visible:outline-tih20-text focus-visible:outline-offset-2 motion-reduce:transition-none">Enroll Now</a>
        </div>
      </div>
    </div>
    <div class="group [perspective:800px] aspect-[3/4]">
      <div class="relative w-full h-full transform-3d transition-transform duration-650 ease-tih20 group-hover:rotate-y-180 focus-within:rotate-y-180 motion-reduce:transition-none motion-reduce:group-hover:rotate-y-0 motion-reduce:focus-within:rotate-y-0">
        <div class="absolute inset-0 flex flex-col justify-end overflow-hidden rounded-2xl backface-hidden bg-[image:url('https://picsum.photos/seed/tih20-bio/600/800'),linear-gradient(145deg,oklch(0.22_0.06_150),oklch(0.35_0.09_150),oklch(0.55_0.13_155),oklch(0.8_0.14_163))] bg-cover bg-center bg-no-repeat motion-reduce:opacity-100 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-0">
          <div class="relative z-1 p-4 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
            <p class="text-sm font-bold text-tih20-text">Bio Systems</p>
            <p class="mt-0.5 text-[10px] text-tih20-muted">Botany Research</p>
          </div>
          <span class="absolute top-2.5 right-2.5 z-2 px-2 py-0.75 rounded-full text-[9px] font-bold text-tih20-muted bg-[oklch(1_0_0/0.07)] border border-[oklch(1_0_0/0.1)] transition-opacity duration-300 group-hover:opacity-0">Hover to flip</span>
        </div>
        <div class="absolute inset-0 flex flex-col items-center justify-center p-5 overflow-hidden rounded-2xl backface-hidden rotate-y-180 bg-linear-[135deg,oklch(0.15_0.05_150),oklch(0.22_0.06_150)] motion-reduce:opacity-0 motion-reduce:rotate-y-0 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-100">
          <span class="mb-3 text-4xl" aria-hidden="true">&#129516;</span>
          <p class="mb-2 text-[15px] font-extrabold text-center text-tih20-text">Lab Access</p>
          <p class="mb-3.5 text-[11px] leading-[1.5] text-center text-tih20-muted">12 months of virtual lab sessions with live microscopy and specimen archives.</p>
          <a href="#bio-join" class="px-4.5 py-2 rounded-full text-[11px] font-bold tracking-[0.05em] text-black no-underline bg-tih20-acc transition-[scale,box-shadow] duration-200 hover:scale-104 hover:shadow-[0_0_16px_oklch(0.8_0.14_163/0.4)] focus-visible:outline-2 focus-visible:outline-tih20-text focus-visible:outline-offset-2 motion-reduce:transition-none">Join Lab</a>
        </div>
      </div>
    </div>
    <div class="group [perspective:800px] aspect-[3/4]">
      <div class="relative w-full h-full transform-3d transition-transform duration-650 ease-tih20 group-hover:rotate-y-180 focus-within:rotate-y-180 motion-reduce:transition-none motion-reduce:group-hover:rotate-y-0 motion-reduce:focus-within:rotate-y-0">
        <div class="absolute inset-0 flex flex-col justify-end overflow-hidden rounded-2xl backface-hidden bg-[image:url('https://picsum.photos/seed/tih20-arts/600/800'),linear-gradient(145deg,oklch(0.25_0.13_305),oklch(0.4_0.19_302),oklch(0.55_0.22_300),oklch(0.78_0.19_320))] bg-cover bg-center bg-no-repeat motion-reduce:opacity-100 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-0">
          <div class="relative z-1 p-4 bg-linear-[to_top,oklch(0_0_0/0.8),transparent]">
            <p class="text-sm font-bold text-tih20-text">Digital Arts</p>
            <p class="mt-0.5 text-[10px] text-tih20-muted">Creative Studio</p>
          </div>
          <span class="absolute top-2.5 right-2.5 z-2 px-2 py-0.75 rounded-full text-[9px] font-bold text-tih20-muted bg-[oklch(1_0_0/0.07)] border border-[oklch(1_0_0/0.1)] transition-opacity duration-300 group-hover:opacity-0">Hover to flip</span>
        </div>
        <div class="absolute inset-0 flex flex-col items-center justify-center p-5 overflow-hidden rounded-2xl backface-hidden rotate-y-180 bg-linear-[135deg,oklch(0.17_0.09_310),oklch(0.25_0.13_305)] motion-reduce:opacity-0 motion-reduce:rotate-y-0 motion-reduce:transition-opacity motion-reduce:duration-300 motion-reduce:group-hover:opacity-100">
          <span class="mb-3 text-4xl" aria-hidden="true">&#127912;</span>
          <p class="mb-2 text-[15px] font-extrabold text-center text-tih20-text">Creator Pack</p>
          <p class="mb-3.5 text-[11px] leading-[1.5] text-center text-tih20-muted">Unlimited generative art tools, 500+ premium assets and weekly critique sessions.</p>
          <a href="#arts-access" class="px-4.5 py-2 rounded-full text-[11px] font-bold tracking-[0.05em] text-black no-underline bg-tih20-acc2 transition-[scale,box-shadow] duration-200 hover:scale-104 hover:shadow-[0_0_16px_oklch(0.78_0.19_320/0.4)] focus-visible:outline-2 focus-visible:outline-tih20-text focus-visible:outline-offset-2 motion-reduce:transition-none">Get Access</a>
        </div>
      </div>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tih20-bg: #07070f;
  --color-tih20-bg: oklch(0.11 0.012 285);
  --color-tih20-text: #f1f5f9;
  --color-tih20-text: oklch(0.96 0.005 250);
  --color-tih20-muted: #64748b;
  --color-tih20-muted: oklch(0.68 0.03 255);
  --color-tih20-acc: #34d399;
  --color-tih20-acc: oklch(0.8 0.14 163);
  --color-tih20-acc2: #e879f9;
  --color-tih20-acc2: oklch(0.78 0.19 320);
  --font-tih20-sans: 'Space Grotesk', system-ui, sans-serif;
  --ease-tih20: cubic-bezier(0.45, 0, 0.55, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
   w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */

.tih-20 {
  width: 100%;
  min-height: 100svh;
}

.tih-20 ::selection {
  background: oklch(0.8 0.14 163);
  color: #000;
}
/* Firefox subpixel artefacts on face edges inside a 3D context. A bug workaround,
   which is exactly the category that should stay out of the markup. */

.tih-20 .backface-hidden {
  border: 1px solid transparent;
}
```

How this works

Four properties, four utilities.

<div class="[perspective:800px] aspect-[3/4]">          <!-- scene -->
  <div class="relative w-full h-full transform-3d
     transition-transform duration-650
     group-hover:rotate-y-180">                   <!-- flipper -->
    <div class="absolute inset-0 backface-hidden">…front
    <div class="absolute inset-0 backface-hidden rotate-y-180">…back

Drop transform-3d and the faces flatten into a scale-through. Drop backface-hidden and both faces show at once. Because all four live in class lists on the three elements, the structure is auditable at a glance — which is not true of four declarations spread over three rules.

Never clip the flipper. overflow-hidden on an element with transform-style: preserve-3d breaks the 3D context in every engine. The rounding and clipping go on the faces instead, and the utility split makes that easy to keep straight.

Reduced motion gets a cross-fade. A 180° rotation is exactly the kind of motion the media query exists for, so motion-reduce: cancels the rotation and swaps the faces by opacity instead.

Make it yours

  • Axis: rotate-x-180 on both the back face and the hover state for a vertical flip.
  • Pace: duration-650 → duration-400 for a snap, duration-900 for a slow turn.
  • Depth: the 800px in the scene's perspective — smaller is more dramatic.
  • Tap to flip: add a data-flipped attribute and a group-data-flipped:rotate-y-180 variant alongside the hover one; four lines of JS for touch.
  • Retheme through --color-tih20-acc; the CTA and focus rings read it.

Gotchas — read before shipping

  • overflow-hidden and transform-3d must never share an element — the 3D context collapses. Put the clip on the faces.
  • Both faces need backface-hidden, not just the back one.
  • The back face must be pre-rotated 180°, or it arrives mirrored.
  • Hover-only flipping hides the back face's CTA from keyboard users; focus-within:rotate-y-180 is the two-word fix.
  • Firefox can show subpixel artefacts on face edges in a 3D context; the transparent hairline border stays in the stylesheet for that.
  • The browser CDN build compiles in the page and is for prototyping only. Ship the CLI or a plugin build.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

3D transforms are broadly supported; backface-hidden emits the -webkit- prefix automatically, which hand-written CSS has to remember.

Techniques used in this demo

Search CodeFronts

Loading…