卡片扇形展开
一叠整齐的卡片在悬停时像手里的扑克牌一样扇形展开,一眼就能看到下面有什么。
灵感
草稿
定稿
用纯 CSS 制作悬停时扇形展开的三张卡片。三张卡片叠放在同一个 grid 单元格中,静止时有轻微偏移(rotate -2deg、0deg、2deg)。在整组 :hover 或 :focus-within 时,分别变为 rotate(-14deg) translateX(-56px)、rotate(0) translateY(-8px)、rotate(14deg) translateX(56px),transform-origin 设在底部中央,让它们像手里的扑克牌一样展开。transform 过渡 420ms,缓动 cubic-bezier(0.34, 1.56, 0.64, 1),并用 transition-delay 0、40、80ms 错开。整组设置 tabindex 0,键盘用户也能展开。在 prefers-reduced-motion 下直接显示展开后的布局,不做过渡。卡片文字为“灵感”“草稿”“定稿”。
源代码
'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; }
}