Stack Fan Out
A tidy stack of cards fans out like a hand of playing cards on hover, showing what is underneath at a glance.
Create a stack of three cards that fans out on hover in pure CSS. Stack the cards in one grid cell with a small resting offset (rotate -2deg, 0deg, 2deg). On :hover or :focus-within of the group, move them to rotate(-14deg) translateX(-56px), rotate(0) translateY(-8px), and rotate(14deg) translateX(56px), with transform-origin at the bottom centre so they pivot like a hand of cards. Transition transform over 420ms with cubic-bezier(0.34, 1.56, 0.64, 1) and stagger with transition-delay 0, 40, and 80ms. Make the group focusable with tabindex 0 so keyboard users can open it. Under prefers-reduced-motion, show the fanned layout without the transition. The cards read "Ideas", "Drafts", and "Final".
Source
'use client'
import s from './demo.module.css'
export default function StackFan({ labels }: { labels: Record<string, string> }) {
return (
<div className={s.stack} tabIndex={0}>
{[labels.a, labels.b, labels.c].map((t) => (
<div key={t} className={s.card}>
{t}
</div>
))}
</div>
)
}
.stack {
display: grid;
border-radius: var(--radius-sm);
outline: none;
}
.card {
grid-area: 1 / 1;
display: grid;
place-items: end start;
width: 110px;
height: 140px;
padding: 12px;
border: 1px solid var(--stage-rule);
border-radius: 12px;
background: var(--stage-surface);
color: var(--stage-ink);
font: 600 var(--text-base) / 1 var(--font-display);
box-shadow: 0 8px 20px oklch(0% 0 0 / 0.3);
transform-origin: 50% 100%;
transition: transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
.card:nth-child(1) { transform: rotate(-2deg); }
.card:nth-child(2) { transform: rotate(0deg); transition-delay: 40ms; }
.card:nth-child(3) { transform: rotate(2deg); transition-delay: 80ms; background: var(--stage-accent); color: var(--stage-accent-ink); border-color: transparent; }
.stack:hover .card:nth-child(1), .stack:focus-within .card:nth-child(1) { transform: rotate(-14deg) translateX(-56px); }
.stack:hover .card:nth-child(2), .stack:focus-within .card:nth-child(2) { transform: translateY(-8px); }
.stack:hover .card:nth-child(3), .stack:focus-within .card:nth-child(3) { transform: rotate(14deg) translateX(56px); }
.stack:focus-visible .card:nth-child(3) { outline: 2px solid var(--color-focus); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
.card { transition: none; }
}