Pure TailwindMIT licensed

Tailwind CSS 3D Flip Pricing Cards

Click “View details” and the whole pricing card turns 180° to reveal specs and fine print on its back. Tailwind v4 ships the 3D kit natively — perspective-[1400px], transform-3d, backface-hidden, rotate-y-180 — so the entire flip is a hidden checkbox and group-has-checked/f:. No JavaScript, and focus can never land on the face you can't see.

Live Demo
Plain CSSTailwind v4
Try it

Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49

Cruip · Affiliate link

Browse Cruip templates

The code

<section class="tpt-10 w-full min-h-svh grid place-items-center bg-tpt10-bg px-5 py-16 font-tpt10-sans text-tpt10-ink antialiased" aria-label="Pricing cards that flip to show plan details">
  <div class="grid w-full max-w-5xl justify-items-center gap-10">
    <h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-extrabold tracking-[-0.03em]">Every detail, one flip away</h2>
    <div class="grid w-full gap-5 md:grid-cols-3">
      <div class="group/f perspective-[1400px]">
        <input type="checkbox" id="tpt10-a" class="peer sr-only" aria-label="Show Launch plan details">
        <div class="grid h-full rounded-[20px] transition-transform duration-700 ease-[cubic-bezier(.5,0,.2,1)] transform-3d group-has-checked/f:rotate-y-180 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tpt10-acc motion-reduce:transition-none">
          <article class="col-start-1 row-start-1 flex flex-col gap-3 rounded-[20px] border border-tpt10-line bg-white p-7 backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:invisible">
            <h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt10-mut uppercase">Launch</h3>
            <p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$25<small class="text-[15px] font-semibold tracking-normal text-tpt10-mut">/mo</small></p>
            <p class="flex-1 text-sm leading-relaxed text-tpt10-body">For new stores finding their footing.</p>
            <a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt10-line text-sm font-bold text-tpt10-ink no-underline transition-colors hover:border-tpt10-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt10-acc">Choose Launch</a>
            <label for="tpt10-a" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-ink transition-colors hover:bg-tpt10-acc/10">View details ⟳</label>
          </article>
          <article class="invisible col-start-1 row-start-1 flex rotate-y-180 flex-col gap-3 rounded-[20px] bg-tpt10-ink p-7 text-tpt10-bg backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:visible">
            <h4 class="text-[15px] font-bold">Launch — details</h4>
            <ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt10-back-body *:flex *:gap-2.5 *:before:text-tpt10-acc-lite *:before:content-['•']"><li>1 staff account</li><li>2.9% + 30¢ per online sale</li><li>Basic reports</li><li>14-day trial, cancel anytime</li></ul>
            <label for="tpt10-a" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-lite transition-colors hover:bg-white/8">⟲ Back</label>
          </article>
        </div>
      </div>
      <div class="group/f perspective-[1400px]">
        <input type="checkbox" id="tpt10-b" class="peer sr-only" aria-label="Show Grow plan details">
        <div class="grid h-full rounded-[20px] transition-transform duration-700 ease-[cubic-bezier(.5,0,.2,1)] transform-3d group-has-checked/f:rotate-y-180 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tpt10-acc motion-reduce:transition-none">
          <article class="relative col-start-1 row-start-1 flex flex-col gap-3 rounded-[20px] bg-white p-7 shadow-[0_18px_40px_-24px_var(--color-tpt10-acc)] ring-2 ring-tpt10-acc backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:invisible">
            <h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt10-acc-ink uppercase">Grow</h3>
            <p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$65<small class="text-[15px] font-semibold tracking-normal text-tpt10-mut">/mo</small></p>
            <p class="flex-1 text-sm leading-relaxed text-tpt10-body">For stores scaling past six figures.</p>
            <a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt10-acc text-sm font-bold text-white no-underline transition-colors hover:bg-tpt10-acc-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt10-acc">Choose Grow</a>
            <label for="tpt10-b" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-ink transition-colors hover:bg-tpt10-acc/10">View details ⟳</label>
          </article>
          <article class="invisible col-start-1 row-start-1 flex rotate-y-180 flex-col gap-3 rounded-[20px] bg-tpt10-ink p-7 text-tpt10-bg backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:visible">
            <h4 class="text-[15px] font-bold">Grow — details</h4>
            <ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt10-back-body *:flex *:gap-2.5 *:before:text-tpt10-acc-lite *:before:content-['•']"><li>5 staff accounts</li><li>2.4% + 30¢ per online sale</li><li>Advanced reports &amp; forecasts</li><li>Abandoned-cart recovery</li></ul>
            <label for="tpt10-b" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-lite transition-colors hover:bg-white/8">⟲ Back</label>
          </article>
        </div>
      </div>
      <div class="group/f perspective-[1400px]">
        <input type="checkbox" id="tpt10-c" class="peer sr-only" aria-label="Show Advanced plan details">
        <div class="grid h-full rounded-[20px] transition-transform duration-700 ease-[cubic-bezier(.5,0,.2,1)] transform-3d group-has-checked/f:rotate-y-180 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tpt10-acc motion-reduce:transition-none">
          <article class="col-start-1 row-start-1 flex flex-col gap-3 rounded-[20px] border border-tpt10-line bg-white p-7 backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:invisible">
            <h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt10-mut uppercase">Advanced</h3>
            <p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$199<small class="text-[15px] font-semibold tracking-normal text-tpt10-mut">/mo</small></p>
            <p class="flex-1 text-sm leading-relaxed text-tpt10-body">For high-volume, multi-region brands.</p>
            <a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt10-line text-sm font-bold text-tpt10-ink no-underline transition-colors hover:border-tpt10-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt10-acc">Choose Advanced</a>
            <label for="tpt10-c" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-ink transition-colors hover:bg-tpt10-acc/10">View details ⟳</label>
          </article>
          <article class="invisible col-start-1 row-start-1 flex rotate-y-180 flex-col gap-3 rounded-[20px] bg-tpt10-ink p-7 text-tpt10-bg backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:visible">
            <h4 class="text-[15px] font-bold">Advanced — details</h4>
            <ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt10-back-body *:flex *:gap-2.5 *:before:text-tpt10-acc-lite *:before:content-['•']"><li>15 staff accounts</li><li>1.9% + 30¢ per online sale</li><li>Custom report builder</li><li>Duty &amp; tax calculators</li></ul>
            <label for="tpt10-c" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-lite transition-colors hover:bg-white/8">⟲ Back</label>
          </article>
        </div>
      </div>
    </div>
    <p aria-hidden="true" class="rounded-full border border-tpt10-line bg-white px-3.5 py-2 font-tpt10-mono text-[11.5px] text-tpt10-mut">perspective-[1400px] · transform-3d · backface-hidden · rotate-y-180</p>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tpt10-bg: #eef2f6;
  --color-tpt10-bg: oklch(0.96 0.008 245);
  --color-tpt10-ink: #15202c;
  --color-tpt10-ink: oklch(0.24 0.03 250);
  --color-tpt10-body: #4b596a;
  --color-tpt10-body: oklch(0.45 0.03 250);
  --color-tpt10-back-body: #d3dbe5;
  --color-tpt10-back-body: oklch(0.88 0.015 250);
  --color-tpt10-mut: #5d6b7d;
  --color-tpt10-mut: oklch(0.51 0.03 250);
  --color-tpt10-line: #dce3eb;
  --color-tpt10-line: oklch(0.91 0.012 245);
  --color-tpt10-acc: #1a86d4;
  --color-tpt10-acc: oklch(0.6 0.15 245);
  --color-tpt10-acc-ink: #0f65a6;
  --color-tpt10-acc-ink: oklch(0.5 0.13 248);
  --color-tpt10-acc-lite: #8cc6f5;
  --color-tpt10-acc-lite: oklch(0.8 0.09 240);
  --font-tpt10-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tpt10-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */

.tpt-10 {
  width: 100%;
  min-height: 100svh;
}

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-tpt10-bg: #eef2f6;
  --color-tpt10-bg: oklch(0.96 0.008 245);
  --color-tpt10-ink: #15202c;
  --color-tpt10-ink: oklch(0.24 0.03 250);
  --color-tpt10-body: #4b596a;
  --color-tpt10-body: oklch(0.45 0.03 250);
  --color-tpt10-back-body: #d3dbe5;
  --color-tpt10-back-body: oklch(0.88 0.015 250);
  --color-tpt10-mut: #5d6b7d;
  --color-tpt10-mut: oklch(0.51 0.03 250);
  --color-tpt10-line: #dce3eb;
  --color-tpt10-line: oklch(0.91 0.012 245);
  --color-tpt10-acc: #1a86d4;
  --color-tpt10-acc: oklch(0.6 0.15 245);
  --color-tpt10-acc-ink: #0f65a6;
  --color-tpt10-acc-ink: oklch(0.5 0.13 248);
  --color-tpt10-acc-lite: #8cc6f5;
  --color-tpt10-acc-lite: oklch(0.8 0.09 240);
  --font-tpt10-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tpt10-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */

.tpt-10 {
  width: 100%;
  min-height: 100svh;
}
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=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap">

What changed in the port

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

  • perspective, transform-style:preserve-3d, backface-visibility:hidden and rotateY(180deg) are all first-class v4 utilities now — the port needs no CSS beyond tokens.
  • .prc-10__scene:has(.prc-10__sr:checked) … became group-has-checked/f: on each scene; three scenes, three named groups, zero cross-talk.
  • UI upgrade from the CSS original: each checkbox now has a descriptive aria-label (&ldquo;Show Grow plan details&rdquo;), and the flip controls are 44px tall (were ~30px).
  • UI upgrade: the back face gained a lighter accent (acc-lite) that clears 7:1 on the dark face, and fees are qualified as &ldquo;per online sale&rdquo; — the fine print buyers look for.
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 CSS 3D Flip Pricing Cards
Source: https://codefronts.com/components/tailwind-css-pricing-tables/tailwind-css-3d-flip-pricing-cards/

Click &ldquo;View details&rdquo; and the whole pricing card turns 180&deg; to reveal specs and fine print on its back. Tailwind v4 ships the 3D kit natively — perspective-[1400px], transform-3d, backface-hidden, rotate-y-180 — so the entire flip is a hidden checkbox and group-has-checked/f:. No JavaScript, and focus can never land on the face you can't see.
## HTML
```html
<section class="tpt-10 w-full min-h-svh grid place-items-center bg-tpt10-bg px-5 py-16 font-tpt10-sans text-tpt10-ink antialiased" aria-label="Pricing cards that flip to show plan details">
  <div class="grid w-full max-w-5xl justify-items-center gap-10">
    <h2 class="text-center text-[clamp(26px,3.8vw,40px)] font-extrabold tracking-[-0.03em]">Every detail, one flip away</h2>
    <div class="grid w-full gap-5 md:grid-cols-3">
      <div class="group/f perspective-[1400px]">
        <input type="checkbox" id="tpt10-a" class="peer sr-only" aria-label="Show Launch plan details">
        <div class="grid h-full rounded-[20px] transition-transform duration-700 ease-[cubic-bezier(.5,0,.2,1)] transform-3d group-has-checked/f:rotate-y-180 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tpt10-acc motion-reduce:transition-none">
          <article class="col-start-1 row-start-1 flex flex-col gap-3 rounded-[20px] border border-tpt10-line bg-white p-7 backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:invisible">
            <h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt10-mut uppercase">Launch</h3>
            <p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$25<small class="text-[15px] font-semibold tracking-normal text-tpt10-mut">/mo</small></p>
            <p class="flex-1 text-sm leading-relaxed text-tpt10-body">For new stores finding their footing.</p>
            <a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt10-line text-sm font-bold text-tpt10-ink no-underline transition-colors hover:border-tpt10-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt10-acc">Choose Launch</a>
            <label for="tpt10-a" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-ink transition-colors hover:bg-tpt10-acc/10">View details ⟳</label>
          </article>
          <article class="invisible col-start-1 row-start-1 flex rotate-y-180 flex-col gap-3 rounded-[20px] bg-tpt10-ink p-7 text-tpt10-bg backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:visible">
            <h4 class="text-[15px] font-bold">Launch — details</h4>
            <ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt10-back-body *:flex *:gap-2.5 *:before:text-tpt10-acc-lite *:before:content-['•']"><li>1 staff account</li><li>2.9% + 30¢ per online sale</li><li>Basic reports</li><li>14-day trial, cancel anytime</li></ul>
            <label for="tpt10-a" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-lite transition-colors hover:bg-white/8">⟲ Back</label>
          </article>
        </div>
      </div>
      <div class="group/f perspective-[1400px]">
        <input type="checkbox" id="tpt10-b" class="peer sr-only" aria-label="Show Grow plan details">
        <div class="grid h-full rounded-[20px] transition-transform duration-700 ease-[cubic-bezier(.5,0,.2,1)] transform-3d group-has-checked/f:rotate-y-180 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tpt10-acc motion-reduce:transition-none">
          <article class="relative col-start-1 row-start-1 flex flex-col gap-3 rounded-[20px] bg-white p-7 shadow-[0_18px_40px_-24px_var(--color-tpt10-acc)] ring-2 ring-tpt10-acc backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:invisible">
            <h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt10-acc-ink uppercase">Grow</h3>
            <p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$65<small class="text-[15px] font-semibold tracking-normal text-tpt10-mut">/mo</small></p>
            <p class="flex-1 text-sm leading-relaxed text-tpt10-body">For stores scaling past six figures.</p>
            <a href="#" class="grid min-h-11 place-items-center rounded-xl bg-tpt10-acc text-sm font-bold text-white no-underline transition-colors hover:bg-tpt10-acc-ink focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt10-acc">Choose Grow</a>
            <label for="tpt10-b" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-ink transition-colors hover:bg-tpt10-acc/10">View details ⟳</label>
          </article>
          <article class="invisible col-start-1 row-start-1 flex rotate-y-180 flex-col gap-3 rounded-[20px] bg-tpt10-ink p-7 text-tpt10-bg backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:visible">
            <h4 class="text-[15px] font-bold">Grow — details</h4>
            <ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt10-back-body *:flex *:gap-2.5 *:before:text-tpt10-acc-lite *:before:content-['•']"><li>5 staff accounts</li><li>2.4% + 30¢ per online sale</li><li>Advanced reports &amp; forecasts</li><li>Abandoned-cart recovery</li></ul>
            <label for="tpt10-b" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-lite transition-colors hover:bg-white/8">⟲ Back</label>
          </article>
        </div>
      </div>
      <div class="group/f perspective-[1400px]">
        <input type="checkbox" id="tpt10-c" class="peer sr-only" aria-label="Show Advanced plan details">
        <div class="grid h-full rounded-[20px] transition-transform duration-700 ease-[cubic-bezier(.5,0,.2,1)] transform-3d group-has-checked/f:rotate-y-180 peer-focus-visible:outline-3 peer-focus-visible:outline-offset-4 peer-focus-visible:outline-tpt10-acc motion-reduce:transition-none">
          <article class="col-start-1 row-start-1 flex flex-col gap-3 rounded-[20px] border border-tpt10-line bg-white p-7 backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:invisible">
            <h3 class="text-[13px] font-bold tracking-[0.08em] text-tpt10-mut uppercase">Advanced</h3>
            <p class="text-[44px] leading-none font-extrabold tracking-[-0.035em]">$199<small class="text-[15px] font-semibold tracking-normal text-tpt10-mut">/mo</small></p>
            <p class="flex-1 text-sm leading-relaxed text-tpt10-body">For high-volume, multi-region brands.</p>
            <a href="#" class="grid min-h-11 place-items-center rounded-xl border-[1.5px] border-tpt10-line text-sm font-bold text-tpt10-ink no-underline transition-colors hover:border-tpt10-acc focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpt10-acc">Choose Advanced</a>
            <label for="tpt10-c" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-ink transition-colors hover:bg-tpt10-acc/10">View details ⟳</label>
          </article>
          <article class="invisible col-start-1 row-start-1 flex rotate-y-180 flex-col gap-3 rounded-[20px] bg-tpt10-ink p-7 text-tpt10-bg backface-hidden [transition:visibility_0s_.35s] group-has-checked/f:visible">
            <h4 class="text-[15px] font-bold">Advanced — details</h4>
            <ul class="grid flex-1 content-start gap-2.5 text-sm text-tpt10-back-body *:flex *:gap-2.5 *:before:text-tpt10-acc-lite *:before:content-['•']"><li>15 staff accounts</li><li>1.9% + 30¢ per online sale</li><li>Custom report builder</li><li>Duty &amp; tax calculators</li></ul>
            <label for="tpt10-c" class="grid min-h-11 cursor-pointer place-items-center rounded-xl text-[13px] font-bold text-tpt10-acc-lite transition-colors hover:bg-white/8">⟲ Back</label>
          </article>
        </div>
      </div>
    </div>
    <p aria-hidden="true" class="rounded-full border border-tpt10-line bg-white px-3.5 py-2 font-tpt10-mono text-[11.5px] text-tpt10-mut">perspective-[1400px] · transform-3d · backface-hidden · rotate-y-180</p>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tpt10-bg: #eef2f6;
  --color-tpt10-bg: oklch(0.96 0.008 245);
  --color-tpt10-ink: #15202c;
  --color-tpt10-ink: oklch(0.24 0.03 250);
  --color-tpt10-body: #4b596a;
  --color-tpt10-body: oklch(0.45 0.03 250);
  --color-tpt10-back-body: #d3dbe5;
  --color-tpt10-back-body: oklch(0.88 0.015 250);
  --color-tpt10-mut: #5d6b7d;
  --color-tpt10-mut: oklch(0.51 0.03 250);
  --color-tpt10-line: #dce3eb;
  --color-tpt10-line: oklch(0.91 0.012 245);
  --color-tpt10-acc: #1a86d4;
  --color-tpt10-acc: oklch(0.6 0.15 245);
  --color-tpt10-acc-ink: #0f65a6;
  --color-tpt10-acc-ink: oklch(0.5 0.13 248);
  --color-tpt10-acc-lite: #8cc6f5;
  --color-tpt10-acc-lite: oklch(0.8 0.09 240);
  --font-tpt10-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tpt10-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities. */

.tpt-10 {
  width: 100%;
  min-height: 100svh;
}
```

How this works

Native 3D utilities. v4 added the full set the CSS original wrote by hand:

<div class="group/f perspective-[1400px]">
  <input type="checkbox" class="peer sr-only">
  <div class="grid transform-3d transition-transform duration-700
    group-has-checked/f:rotate-y-180">
    <article class="backface-hidden …">front</article>
    <article class="backface-hidden rotate-y-180 …">back</article>

Grid stacking, not absolute. Both faces share one grid cell, so the card is exactly as tall as its taller face — nothing clips, CLS stays zero.

Visibility swaps at the midpoint. [transition:visibility_0s_.35s] flips each face's visibility halfway through the turn, exactly when it's edge-on.

Make it yours

  • Flip on hover too: add group-hover/f:rotate-y-180 (keep click for touch).
  • More drama: perspective-[800px].
  • Top hinge: swap rotate-y-180 for rotate-x-180 on the wrapper and back face.
  • Put a testimonial or spec table on the back — it's an ordinary card.

Gotchas — read before shipping

  • Don't put overflow-hidden on the transform-3d wrapper — it flattens the 3D context.
  • Without the visibility swap, keyboard users tab into invisible links on the back.
  • backface-hidden must be on each face, not on the wrapper.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

3D transforms are universal; :has() drives the checked-state flip.

Techniques used in this demo

Search CodeFronts

Loading…