36 Tailwind Stacked Cards
33 / 36

All 36 in 36 Tailwind Stacked Cards

  1. 01Tailwind Scroll-Driven Scaling Card Stack
  2. 02Tailwind Swipe Card Deck Drag to Dismiss
  3. 03Tailwind Glassmorphism Testimonial Card Stack
  4. 04Tailwind Stacked Cards Expand Accordion on Click
  5. 05Tailwind Fan Out Photo Stack on Hover
  6. 06Tailwind 3D Perspective Tilt Card Stack
  7. 07Tailwind Multi Step Form Card Stack
  8. 08Tailwind Tabbed Card Stack Bring to Front
  9. 09Tailwind Click to Front Stacked Cards Cycle
  10. 10Tailwind Classic Card Deck Stack Shadow
  11. 11Tailwind Fan Spread Hand of Cards
  12. 12Tailwind Polaroid Photo Stack Scattered Rotate
  13. 13Tailwind Staircase Offset Stacked Cards Cascade
  14. 14Tailwind Cards Spread Out Horizontally on Hover
  15. 15Tailwind Stacked Cards Lift on Hover Sibling Push
  16. 16Tailwind Accordion Stacked Cards Slide Out Menu
  17. 17Tailwind Shuffle Cards Animation Loop Deck
  18. 18Tailwind File Folder Tab Stacked Cards
  19. 19Tailwind Scattered Photos Pinch to Centre on Hover
  20. 20Tailwind Mobile Swipe Card Stack Translate3d
  21. 21Tailwind Single Accordion Card Nested Layers
  22. 22Tailwind Isometric Tower Stacked Cards 3D Column
  23. 23Tailwind 3D Flip Card Stack Reveal Back
  24. 24Tailwind Card Stack Tilt on Hover Quadrant
  25. 25Tailwind Notification Stack Pile Dismiss
  26. 26Tailwind Receipt Roll Unroll Stacked Items
  27. 27Tailwind Scratch Card Reveal Canvas Mask
  28. 28Tailwind Stacked Cards Hover Reveal Spread
  29. 29Tailwind Scroll Activated Sticky Stacking Cards
  30. 30Tailwind Stacked Testimonial Slider Radio
  31. 31Tailwind Isometric Overlapping Stacked Cards
  32. 32Tailwind Bento Grid Stacked Cards Hover Fan
  33. 33Tailwind Perspective Card Deck Depth Tunnel
  34. 34Tailwind Peel Back Corner Card Reveal
  35. 35Tailwind Timeline Stacked Milestone Cards
  36. 36Tailwind Spiral Tower Rotating Stacked Cards
Tailwind v4MIT licensed

Tailwind Perspective Card Deck Depth Tunnel

Four panels receding into the screen on negative Z, tilting as a group on hover while the front card pushes toward you. Four :nth-child rules become one index expression — depth, vertical offset and opacity all fall out of --i — and the opacity ramp doubles as the contrast fix, because a panel that recedes should also read as background.

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="stk-33 grid w-full min-h-svh place-items-center px-5 py-15 font-stk33-sans bg-stk33-bg [background-image:radial-gradient(circle_at_50%_50%,var(--color-stk33-glow),transparent_70%)]" aria-label="Sector status deck">
  <div class="group h-95 w-75 [perspective:900px]">
    <div class="relative size-full [transform-style:preserve-3d] transition-transform duration-800 ease-out group-hover:[transform:rotateX(18deg)_rotateY(-12deg)] motion-reduce:transition-none motion-reduce:rotate-none!">
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 group-hover:[transform:translateZ(60px)] motion-reduce:transition-none" style="--i:0">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 01</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Active node // online</p>
      </article>
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 motion-reduce:transition-none" style="--i:1" aria-hidden="true">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 02</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Buffered // standby</p>
      </article>
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 motion-reduce:transition-none" style="--i:2" aria-hidden="true">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 03</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Cached // idle</p>
      </article>
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 motion-reduce:transition-none" style="--i:3" aria-hidden="true">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 04</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Archived // sleep</p>
      </article>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-stk33-bg: #05060a;
  --color-stk33-bg: oklch(0.08 0.012 275);
  --color-stk33-glow: #10131f;
  --color-stk33-glow: oklch(0.19 0.022 275);
  --color-stk33-c1: #28345a;
  --color-stk33-c1: oklch(0.32 0.055 265);
  --color-stk33-c2: #121628;
  --color-stk33-c2: oklch(0.20 0.030 270);
  --color-stk33-ink: #cfe0ff;
  --color-stk33-ink: oklch(0.90 0.040 260);
  --color-stk33-neon: #78aaff;
  --color-stk33-neon: oklch(0.74 0.130 260);
  --color-stk33-halo: rgba(70, 120, 255, 0.18);
  --font-stk33-sans: 'Rajdhani', system-ui, sans-serif;
  --font-stk33-display: 'Orbitron', system-ui, sans-serif;
  --ease-stk33: cubic-bezier(0.2, 0.8, 0.2, 1);
}

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-stk33-bg: #05060a;
  --color-stk33-bg: oklch(0.08 0.012 275);
  --color-stk33-glow: #10131f;
  --color-stk33-glow: oklch(0.19 0.022 275);
  --color-stk33-c1: #28345a;
  --color-stk33-c1: oklch(0.32 0.055 265);
  --color-stk33-c2: #121628;
  --color-stk33-c2: oklch(0.20 0.030 270);
  --color-stk33-ink: #cfe0ff;
  --color-stk33-ink: oklch(0.90 0.040 260);
  --color-stk33-neon: #78aaff;
  --color-stk33-neon: oklch(0.74 0.130 260);
  --color-stk33-halo: rgba(70, 120, 255, 0.18);
  --font-stk33-sans: 'Rajdhani', system-ui, sans-serif;
  --font-stk33-display: 'Orbitron', system-ui, sans-serif;
  --ease-stk33: cubic-bezier(0.2, 0.8, 0.2, 1);
}
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=Orbitron:wght@600&family=Rajdhani:wght@500&display=swap">

What changed in the port

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

  • The webfonts load as <link> tags in setup, not as an @import inside the stylesheet. Tailwind emits user @import rules after its own @layer blocks, and a late @import is invalid CSS — the browser drops it and the demo silently falls back to system fonts.
  • Four :nth-child rules become one index expression covering depth, vertical rake and opacity — adding a fifth panel is one attribute.
  • opacity-[calc(1-var(--i)*0.2)] is both the depth cue and the honest answer to contrast: foreshortened text is harder to read than its ratio suggests, so receding panels read as background.
  • The glass uses Tailwind's backdrop-blur-* rather than an arbitrary property, specifically because the utility emits the -webkit- prefix older Safari needs.
  • Two hover scopes fire from one pointer entry: the stage tilts the deck, and the front panel has its own full transform pushing it out of the tunnel.
  • The three background panels are aria-hidden; only the front sector is real content, which keeps four near-identical status lines out of the accessibility tree.
  • motion-reduce:rotate-none! keeps the informative tunnel and removes the tilt, rather than slowing a rotation that is itself the problem.
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 Perspective Card Deck Depth Tunnel
Source: https://codefronts.com/components/tailwind-stacked-cards/tailwind-perspective-card-deck-depth-tunnel/

Four panels receding into the screen on negative Z, tilting as a group on hover while the front card pushes toward you. Four :nth-child rules become one index expression &mdash; depth, vertical offset and opacity all fall out of --i &mdash; and the opacity ramp doubles as the contrast fix, because a panel that recedes should also read as background.
## HTML
```html
<section class="stk-33 grid w-full min-h-svh place-items-center px-5 py-15 font-stk33-sans bg-stk33-bg [background-image:radial-gradient(circle_at_50%_50%,var(--color-stk33-glow),transparent_70%)]" aria-label="Sector status deck">
  <div class="group h-95 w-75 [perspective:900px]">
    <div class="relative size-full [transform-style:preserve-3d] transition-transform duration-800 ease-out group-hover:[transform:rotateX(18deg)_rotateY(-12deg)] motion-reduce:transition-none motion-reduce:rotate-none!">
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 group-hover:[transform:translateZ(60px)] motion-reduce:transition-none" style="--i:0">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 01</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Active node // online</p>
      </article>
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 motion-reduce:transition-none" style="--i:1" aria-hidden="true">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 02</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Buffered // standby</p>
      </article>
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 motion-reduce:transition-none" style="--i:2" aria-hidden="true">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 03</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Cached // idle</p>
      </article>
      <article class="absolute inset-0 flex flex-col justify-end rounded-[20px] border border-stk33-neon/35 bg-linear-[155deg,var(--color-stk33-c1),var(--color-stk33-c2)] p-6.5 text-stk33-ink backdrop-blur-[2px] shadow-[0_0_40px_var(--color-stk33-halo)] opacity-[calc(1-var(--i)*0.2)] [transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))] transition-[transform,opacity] duration-800 ease-stk33 motion-reduce:transition-none" style="--i:3" aria-hidden="true">
        <h3 class="m-0 font-stk33-display text-[1.3rem] tracking-[0.08em]">SECTOR 04</h3>
        <p class="m-0 text-[0.95rem] tracking-[0.05em] text-stk33-ink/75">Archived // sleep</p>
      </article>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-stk33-bg: #05060a;
  --color-stk33-bg: oklch(0.08 0.012 275);
  --color-stk33-glow: #10131f;
  --color-stk33-glow: oklch(0.19 0.022 275);
  --color-stk33-c1: #28345a;
  --color-stk33-c1: oklch(0.32 0.055 265);
  --color-stk33-c2: #121628;
  --color-stk33-c2: oklch(0.20 0.030 270);
  --color-stk33-ink: #cfe0ff;
  --color-stk33-ink: oklch(0.90 0.040 260);
  --color-stk33-neon: #78aaff;
  --color-stk33-neon: oklch(0.74 0.130 260);
  --color-stk33-halo: rgba(70, 120, 255, 0.18);
  --font-stk33-sans: 'Rajdhani', system-ui, sans-serif;
  --font-stk33-display: 'Orbitron', system-ui, sans-serif;
  --ease-stk33: cubic-bezier(0.2, 0.8, 0.2, 1);
}
```

How this works

Negative Z is the whole tunnel. Positive translateZ brings a card toward the viewer; negative pushes it away. Combined with a vertical offset it reads as a corridor:

[transform:translateZ(calc(var(--i)*-80px))_translateY(calc(var(--i)*-26px))]
opacity-[calc(1-var(--i)*0.2)]

Four :nth-child blocks collapse to that, and adding a fifth panel is one more --i.

The opacity ramp is not decoration. A 3D projection foreshortens text on the receding panels, which lowers effective contrast whatever the colour values say. Fading the whole panel is the honest response: it signals ‘this is background’ instead of pretending distant text is readable. The front panel, which carries the content, stays at full strength.

Two hover scopes, one gesture. The stage's group-hover: tilts the deck; the front card has its own group-hover:[transform:translateZ(60px)] that pushes it out of the tunnel. Both fire from the same pointer entry, and because the front card's transform is written in full there is no partial-override surprise.

Glass has a budget. backdrop-filter is GPU-composited and expensive; four panels is about the ceiling on mobile. The blur here is deliberately small (2px) — enough to separate the panels, cheap enough to stay smooth.

Make it yours

  • Change the tunnel depth with the -80px multiplier, and the vertical rake with the -26px.
  • Set the fade rate with the 0.2 factor in the opacity calc.
  • Retune the hover tilt via the stage's rotateX/rotateY pair.
  • Rebrand the neon through --color-stk33-neon; the border and the glow both read it.
  • Add a scanline overlay as one absolutely-positioned repeating-linear-gradient element if you want the full sci-fi register.

Gotchas — read before shipping

  • backdrop-blur needs something behind it to sample — over a flat single-tone background it produces nothing visible.
  • Cap the glass panels at three or four. backdrop-filter is GPU-composited and stacking many of them stutters on mid-range phones.
  • Include the -webkit- prefix for older Safari — Tailwind's backdrop-blur-* emits it, so use the utility rather than an arbitrary property.
  • Dim the receding panels rather than trusting their text contrast; foreshortened type is harder to read than its contrast ratio suggests.
  • perspective on the stage, preserve-3d on the deck. Reversed, the tunnel flattens.
  • Under reduced motion, keep the resting tunnel and drop the tilt — the layout is informative, the rotation is not.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

backdrop-filter is Chrome 76+, Safari 9+ prefixed, Firefox 103+; 3D transforms are universal. The floor is Tailwind v4's own generated sheet.

Techniques used in this demo

Theme tokensset in @theme, used by a utility

Arbitraryneeds bracket syntax

HTML & JSno Tailwind involved

Search CodeFronts

Loading…