10 / 36
All 36 in 36 Tailwind Stacked Cards
- 01Tailwind Scroll-Driven Scaling Card Stack
- 02Tailwind Swipe Card Deck Drag to Dismiss
- 03Tailwind Glassmorphism Testimonial Card Stack
- 04Tailwind Stacked Cards Expand Accordion on Click
- 05Tailwind Fan Out Photo Stack on Hover
- 06Tailwind 3D Perspective Tilt Card Stack
- 07Tailwind Multi Step Form Card Stack
- 08Tailwind Tabbed Card Stack Bring to Front
- 09Tailwind Click to Front Stacked Cards Cycle
- 10Tailwind Classic Card Deck Stack Shadow
- 11Tailwind Fan Spread Hand of Cards
- 12Tailwind Polaroid Photo Stack Scattered Rotate
- 13Tailwind Staircase Offset Stacked Cards Cascade
- 14Tailwind Cards Spread Out Horizontally on Hover
- 15Tailwind Stacked Cards Lift on Hover Sibling Push
- 16Tailwind Accordion Stacked Cards Slide Out Menu
- 17Tailwind Shuffle Cards Animation Loop Deck
- 18Tailwind File Folder Tab Stacked Cards
- 19Tailwind Scattered Photos Pinch to Centre on Hover
- 20Tailwind Mobile Swipe Card Stack Translate3d
- 21Tailwind Single Accordion Card Nested Layers
- 22Tailwind Isometric Tower Stacked Cards 3D Column
- 23Tailwind 3D Flip Card Stack Reveal Back
- 24Tailwind Card Stack Tilt on Hover Quadrant
- 25Tailwind Notification Stack Pile Dismiss
- 26Tailwind Receipt Roll Unroll Stacked Items
- 27Tailwind Scratch Card Reveal Canvas Mask
- 28Tailwind Stacked Cards Hover Reveal Spread
- 29Tailwind Scroll Activated Sticky Stacking Cards
- 30Tailwind Stacked Testimonial Slider Radio
- 31Tailwind Isometric Overlapping Stacked Cards
- 32Tailwind Bento Grid Stacked Cards Hover Fan
- 33Tailwind Perspective Card Deck Depth Tunnel
- 34Tailwind Peel Back Corner Card Reveal
- 35Tailwind Timeline Stacked Milestone Cards
- 36Tailwind Spiral Tower Rotating Stacked Cards
Tailwind Classic Card Deck Stack Shadow
Depth from tone and shadow alone — no colour tricks, no 3D. Four cards share a footprint, stepped by [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))], and the thickness comes from a two-layer shadow: a hard 2px offset for the cut edge, a soft blur for the drop. On hover the same expression runs at a larger step, so one utility describes both the resting deck and the spread.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="stk-10 w-full min-h-svh flex items-center justify-center px-5 py-15 font-stk10-sans bg-stk10-paper" aria-label="Classic card deck">
<div class="group relative w-[min(320px,100%)] h-55 rounded-[20px] outline-none focus-visible:outline-3 focus-visible:outline-stk10-accent focus-visible:outline-offset-8" tabindex="0">
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:3" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:2" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:1" aria-hidden="true"></div>
<div class="absolute inset-0 z-5 rounded-2xl border border-stk10-line bg-stk10-face p-7 shadow-[0_3px_0_var(--color-stk10-edge),0_20px_34px_-18px_rgba(60,50,30,0.55)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:0">
<p class="m-0 font-stk10-mono text-xs font-medium tracking-[0.16em] uppercase text-stk10-accent">Field Notes</p>
<h3 class="mt-2 mb-2.5 text-3xl font-extrabold tracking-[-0.02em] text-stk10-ink">Deck No. 7</h3>
<p class="m-0 max-w-[32ch] text-[15px] leading-relaxed text-stk10-body">Fifty-two ideas, shuffled weekly. Draw one and build it before Friday.</p>
</div>
</div>
</section><section class="stk-10 w-full min-h-svh flex items-center justify-center px-5 py-15 font-stk10-sans bg-stk10-paper" aria-label="Classic card deck">
<div class="group relative w-[min(320px,100%)] h-55 rounded-[20px] outline-none focus-visible:outline-3 focus-visible:outline-stk10-accent focus-visible:outline-offset-8" tabindex="0">
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:3" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:2" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:1" aria-hidden="true"></div>
<div class="absolute inset-0 z-5 rounded-2xl border border-stk10-line bg-stk10-face p-7 shadow-[0_3px_0_var(--color-stk10-edge),0_20px_34px_-18px_rgba(60,50,30,0.55)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:0">
<p class="m-0 font-stk10-mono text-xs font-medium tracking-[0.16em] uppercase text-stk10-accent">Field Notes</p>
<h3 class="mt-2 mb-2.5 text-3xl font-extrabold tracking-[-0.02em] text-stk10-ink">Deck No. 7</h3>
<p class="m-0 max-w-[32ch] text-[15px] leading-relaxed text-stk10-body">Fifty-two ideas, shuffled weekly. Draw one and build it before Friday.</p>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--color-stk10-paper: #e7e4dc;
--color-stk10-paper: oklch(0.91 0.008 85);
--color-stk10-face: #fdfcf9;
--color-stk10-face: oklch(0.99 0.004 85);
--color-stk10-under: #f6f3ec;
--color-stk10-under: oklch(0.96 0.007 85);
--color-stk10-line: #e0dcd0;
--color-stk10-line: oklch(0.89 0.010 85);
--color-stk10-edge: #d9d4c6;
--color-stk10-edge: oklch(0.86 0.014 85);
--color-stk10-ink: #3a3324;
--color-stk10-ink: oklch(0.33 0.020 80);
--color-stk10-body: #6a6250;
--color-stk10-body: oklch(0.50 0.018 80);
--color-stk10-accent: #a89b7c;
--color-stk10-accent: oklch(0.68 0.035 85);
--font-stk10-sans: 'Archivo', system-ui, sans-serif;
--font-stk10-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-stk10: cubic-bezier(0.3, 0.9, 0.3, 1);
}@import "tailwindcss";
@theme {
--color-stk10-paper: #e7e4dc;
--color-stk10-paper: oklch(0.91 0.008 85);
--color-stk10-face: #fdfcf9;
--color-stk10-face: oklch(0.99 0.004 85);
--color-stk10-under: #f6f3ec;
--color-stk10-under: oklch(0.96 0.007 85);
--color-stk10-line: #e0dcd0;
--color-stk10-line: oklch(0.89 0.010 85);
--color-stk10-edge: #d9d4c6;
--color-stk10-edge: oklch(0.86 0.014 85);
--color-stk10-ink: #3a3324;
--color-stk10-ink: oklch(0.33 0.020 80);
--color-stk10-body: #6a6250;
--color-stk10-body: oklch(0.50 0.018 80);
--color-stk10-accent: #a89b7c;
--color-stk10-accent: oklch(0.68 0.035 85);
--font-stk10-sans: 'Archivo', system-ui, sans-serif;
--font-stk10-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-stk10: cubic-bezier(0.3, 0.9, 0.3, 1);
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<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.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-stk10-paper: #e7e4dc;
--color-stk10-paper: oklch(0.91 0.008 85);
--color-stk10-face: #fdfcf9;
--color-stk10-face: oklch(0.99 0.004 85);
--color-stk10-under: #f6f3ec;
--color-stk10-under: oklch(0.96 0.007 85);
--color-stk10-line: #e0dcd0;
--color-stk10-line: oklch(0.89 0.010 85);
--color-stk10-edge: #d9d4c6;
--color-stk10-edge: oklch(0.86 0.014 85);
--color-stk10-ink: #3a3324;
--color-stk10-ink: oklch(0.33 0.020 80);
--color-stk10-body: #6a6250;
--color-stk10-body: oklch(0.50 0.018 80);
--color-stk10-accent: #a89b7c;
--color-stk10-accent: oklch(0.68 0.035 85);
--font-stk10-sans: 'Archivo', system-ui, sans-serif;
--font-stk10-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-stk10: cubic-bezier(0.3, 0.9, 0.3, 1);
}@import "tailwindcss";
@theme {
--color-stk10-paper: #e7e4dc;
--color-stk10-paper: oklch(0.91 0.008 85);
--color-stk10-face: #fdfcf9;
--color-stk10-face: oklch(0.99 0.004 85);
--color-stk10-under: #f6f3ec;
--color-stk10-under: oklch(0.96 0.007 85);
--color-stk10-line: #e0dcd0;
--color-stk10-line: oklch(0.89 0.010 85);
--color-stk10-edge: #d9d4c6;
--color-stk10-edge: oklch(0.86 0.014 85);
--color-stk10-ink: #3a3324;
--color-stk10-ink: oklch(0.33 0.020 80);
--color-stk10-body: #6a6250;
--color-stk10-body: oklch(0.50 0.018 80);
--color-stk10-accent: #a89b7c;
--color-stk10-accent: oklch(0.68 0.035 85);
--font-stk10-sans: 'Archivo', system-ui, sans-serif;
--font-stk10-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-stk10: cubic-bezier(0.3, 0.9, 0.3, 1);
}<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=Archivo:wdth,wght@75..125,400;75..125,800&family=JetBrains+Mono:wght@400;500&display=swap">
<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=Archivo:wdth,wght@75..125,400;75..125,800&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The webfonts load as
<link>tags insetup, not as an@importinside the stylesheet. Tailwind emits user@importrules after its own@layerblocks, and a late@importis invalid CSS — the browser drops it and the demo silently falls back to system fonts. - Eight rules — four resting offsets and four hover twins — become one arbitrary transform and one
group-hover:override, both reading--i. - The layered
box-shadowstays arbitrary, and the hard0_2px_0layer is the whole effect: it is the cut edge of the paper, and no amount of blur substitutes for it. - Tonal separation is two
@themecolours rather than an opacity modifier, because a translucent top card lets the under-card fill bleed through. :not(.card--top)disappears — the under-cards simply carrybg-stk10-underand the top card carriesbg-stk10-face.- The whole demo is four
<div>s and a@themeblock: no keyframes, no:has(), no script, and the only custom property is an integer. - Arbitrary transforms replace rather than compose, so the
group-hover:value repeats both axes — a partial override would silently drop one.
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 Classic Card Deck Stack Shadow
Source: https://codefronts.com/components/tailwind-stacked-cards/tailwind-classic-card-deck-stack-shadow/
Depth from tone and shadow alone — no colour tricks, no 3D. Four cards share a footprint, stepped by [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))], and the thickness comes from a two-layer shadow: a hard 2px offset for the cut edge, a soft blur for the drop. On hover the same expression runs at a larger step, so one utility describes both the resting deck and the spread.
## HTML
```html
<section class="stk-10 w-full min-h-svh flex items-center justify-center px-5 py-15 font-stk10-sans bg-stk10-paper" aria-label="Classic card deck">
<div class="group relative w-[min(320px,100%)] h-55 rounded-[20px] outline-none focus-visible:outline-3 focus-visible:outline-stk10-accent focus-visible:outline-offset-8" tabindex="0">
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:3" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:2" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:1" aria-hidden="true"></div>
<div class="absolute inset-0 z-5 rounded-2xl border border-stk10-line bg-stk10-face p-7 shadow-[0_3px_0_var(--color-stk10-edge),0_20px_34px_-18px_rgba(60,50,30,0.55)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:0">
<p class="m-0 font-stk10-mono text-xs font-medium tracking-[0.16em] uppercase text-stk10-accent">Field Notes</p>
<h3 class="mt-2 mb-2.5 text-3xl font-extrabold tracking-[-0.02em] text-stk10-ink">Deck No. 7</h3>
<p class="m-0 max-w-[32ch] text-[15px] leading-relaxed text-stk10-body">Fifty-two ideas, shuffled weekly. Draw one and build it before Friday.</p>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-stk10-paper: #e7e4dc;
--color-stk10-paper: oklch(0.91 0.008 85);
--color-stk10-face: #fdfcf9;
--color-stk10-face: oklch(0.99 0.004 85);
--color-stk10-under: #f6f3ec;
--color-stk10-under: oklch(0.96 0.007 85);
--color-stk10-line: #e0dcd0;
--color-stk10-line: oklch(0.89 0.010 85);
--color-stk10-edge: #d9d4c6;
--color-stk10-edge: oklch(0.86 0.014 85);
--color-stk10-ink: #3a3324;
--color-stk10-ink: oklch(0.33 0.020 80);
--color-stk10-body: #6a6250;
--color-stk10-body: oklch(0.50 0.018 80);
--color-stk10-accent: #a89b7c;
--color-stk10-accent: oklch(0.68 0.035 85);
--font-stk10-sans: 'Archivo', system-ui, sans-serif;
--font-stk10-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-stk10: cubic-bezier(0.3, 0.9, 0.3, 1);
}
```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 Classic Card Deck Stack Shadow
Source: https://codefronts.com/components/tailwind-stacked-cards/tailwind-classic-card-deck-stack-shadow/
Depth from tone and shadow alone — no colour tricks, no 3D. Four cards share a footprint, stepped by [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))], and the thickness comes from a two-layer shadow: a hard 2px offset for the cut edge, a soft blur for the drop. On hover the same expression runs at a larger step, so one utility describes both the resting deck and the spread.
## HTML
```html
<section class="stk-10 w-full min-h-svh flex items-center justify-center px-5 py-15 font-stk10-sans bg-stk10-paper" aria-label="Classic card deck">
<div class="group relative w-[min(320px,100%)] h-55 rounded-[20px] outline-none focus-visible:outline-3 focus-visible:outline-stk10-accent focus-visible:outline-offset-8" tabindex="0">
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:3" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:2" aria-hidden="true"></div>
<div class="absolute inset-0 rounded-2xl border border-stk10-line bg-stk10-under shadow-[0_2px_0_var(--color-stk10-edge),0_12px_24px_-14px_rgba(60,50,30,0.5)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:1" aria-hidden="true"></div>
<div class="absolute inset-0 z-5 rounded-2xl border border-stk10-line bg-stk10-face p-7 shadow-[0_3px_0_var(--color-stk10-edge),0_20px_34px_-18px_rgba(60,50,30,0.55)] [transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))] transition-transform duration-400 ease-stk10 group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] group-focus-visible:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))] motion-reduce:transition-none" style="--i:0">
<p class="m-0 font-stk10-mono text-xs font-medium tracking-[0.16em] uppercase text-stk10-accent">Field Notes</p>
<h3 class="mt-2 mb-2.5 text-3xl font-extrabold tracking-[-0.02em] text-stk10-ink">Deck No. 7</h3>
<p class="m-0 max-w-[32ch] text-[15px] leading-relaxed text-stk10-body">Fifty-two ideas, shuffled weekly. Draw one and build it before Friday.</p>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-stk10-paper: #e7e4dc;
--color-stk10-paper: oklch(0.91 0.008 85);
--color-stk10-face: #fdfcf9;
--color-stk10-face: oklch(0.99 0.004 85);
--color-stk10-under: #f6f3ec;
--color-stk10-under: oklch(0.96 0.007 85);
--color-stk10-line: #e0dcd0;
--color-stk10-line: oklch(0.89 0.010 85);
--color-stk10-edge: #d9d4c6;
--color-stk10-edge: oklch(0.86 0.014 85);
--color-stk10-ink: #3a3324;
--color-stk10-ink: oklch(0.33 0.020 80);
--color-stk10-body: #6a6250;
--color-stk10-body: oklch(0.50 0.018 80);
--color-stk10-accent: #a89b7c;
--color-stk10-accent: oklch(0.68 0.035 85);
--font-stk10-sans: 'Archivo', system-ui, sans-serif;
--font-stk10-mono: 'JetBrains Mono', ui-monospace, monospace;
--ease-stk10: cubic-bezier(0.3, 0.9, 0.3, 1);
}
```How this works
One expression, two multipliers. The resting step and the hover spread are the same shape of value:
[transform:translate(calc(var(--i)*5px),calc(var(--i)*6px))]
group-hover:[transform:translate(calc(var(--i)*12px),calc(var(--i)*13px))]Four :nth-child offsets and their four hover twins collapse to this, and the deck's depth is now a single number you can tune without counting cards.
Thickness is two shadows, not one. A blurred shadow alone gives a floating card; a card with an edge needs a zero-blur offset first — 0_2px_0_var(--color-stk10-edge) — and the blur second. The top card gets a slightly deeper pair so it reads as the thing you would pick up.
The under-cards are furniture. They carry no content and are marked aria-hidden, so a screen reader hears one card with one title, which is what the design actually means. The top card stays fully opaque, because a translucent face would let the lower fills bleed through and destroy the tonal separation the whole effect depends on.
Make it yours
- Deepen the deck by adding a card with the next
--i; nothing else changes. - Tune the thickness by editing the hard
0_2px_0layer and its--color-stk10-edgetoken. - Change the spread with the
12px/13pxmultipliers in thegroup-hover:transform. - Restyle the top card's content freely — it is the only card with any.
- Swap the paper palette through
--color-stk10-face/-under/-edge.
Gotchas — read before shipping
- Mark the decorative cards
aria-hidden. Four identical empty cards in the accessibility tree is noise, not depth. - Keep the top card opaque. Any transparency and the under-card tone shows through as a muddy tint.
- Use an offset shadow with zero blur for the edge. Blur alone always reads as float, never as thickness.
- The hover transform must repeat the whole
translate(). Arbitrary transforms replace rather than compose, so a partial value loses the other axis. - Put the focus ring on the wrapper, not the cards; the cards are decorative and the wrapper is what receives focus.
- Give the stage room for the spread — at
--i:3the hover offset is 36px right and 39px down.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Transforms, calc() with custom properties and layered box-shadow are universal (Chrome 49+, Safari 10+, Firefox 52+). The floor is Tailwind v4's own generated sheet.