SuperAPI AI 工具集

stacked-cards

前端与建站

查看项目

更新于 10-16 05:30

技能介绍

用途

Stacked Cards 是一种前端界面实现模式,用于创建水平扇形展开或层叠排布的卡片堆栈。卡片按顺序相互重叠,鼠标悬停时卡片在原地向上抬起,同时保持原有的层叠关系不被破坏。该模式适合构建专辑浏览器、卡片扇形展示、堆叠卡片列表等交互场景。

解决的问题

资料指出层叠卡片常出现三个 bug:

  1. 堆叠顺序错误:数组中靠后的卡片显示在上层。
  2. 悬停破坏层叠:在悬停时改变 z-index,扰乱了视觉顺序。
  3. Tooltip 被困在堆叠上下文中:卡片内部的 Tooltip 无法突破父级的 z-index 限制。

该模式声称同时解决这三个问题。

核心概念

  • 数组中第一个元素位于最前(z-index 最高)。
  • 后续每个元素位于其后并向右偏移。
  • 悬停时卡片向上抬起,但不改变 z-index。

核心实现

实现基于 React 与 Next.js(".use client"、useState、next/image),关键点如下:

1. 反转渲染顺序

正确做法是使用 [...cards].reverse().map(),让第一张卡片在 DOM 中最后渲染,从而显示在最上层;并通过 const cardIndex = arr.length - 1 - renderIndex; 将渲染索引转换回实际卡片索引。资料说明原因:当同一父级内 z-index 相同时,DOM 顺序决定堆叠顺序。

2. 悬停时不改变 z-index

z-index 仅由位置决定:const zIndex = arr.length - cardIndex;。若在悬停时修改 z-index,卡片会跳到最前,破坏物理堆叠的视觉错觉;真实卡片的抬起应保持在前面卡片之后。

3. 仅做悬停位移(不缩放)

const translateY = hoveredIndex === cardIndex ? -20 : 0;。资料建议避免使用 scale,因为缩放会让卡片视觉上"弹出"。

4. Tooltip 放在堆叠上下文之外

错误做法是将 Tooltip 放在卡片 div 内部,会被父级 z-index 困住,即使设置 z-50 也无效。正确做法是将 Tooltip 作为兄弟元素渲染在卡片循环之外。原因:子元素无法逃出父级的堆叠上下文。

5. 居中公式

const spacing = 40;      // Horizontal offset between cards
const cardSize = 130;    // Card width
const stackWidth = (cards.length - 1) * spacing + cardSize;

每张卡片的水平偏移:const translateX = -stackWidth / 2 + cardIndex * spacing + cardSize / 2;

然后配合 left-1/2 与 translateX(calc(-50% + ${translateX}px)) 实现居中。

6. 导航时清除悬停状态

在切换卡片选择与返回列表视图时调用 setHoveredIndex(null);,否则返回列表视图时先前悬停的卡片仍会保持抬起状态。

Tooltip 位置计算

资料给出的计算:容器高度 180px、卡片高度 130px、抬起 20px 时,抬起后卡片顶部 = 中心 - 半卡高 - 抬起 = 90 - 65 - 20 = 5px。Tooltip 位置为 calc(50% - 95px)(即中心 50% - 半卡高 65px - 抬起 20px - 间隙 10px),并用 translateY(-100%) 向上移动自身高度。

尺寸变体

场景 卡片尺寸 间距 抬起 容器高度
预览 80px 28px -12px 110px
完整 130px 40px -20px 180px

明暗模式变体

元素 浅色模式 深色模式
卡片阴影 shadow-zinc-400/50 shadow-black/70
Tooltip 背景 bg-white/95 bg-zinc-800/95
Tooltip 边框 border-zinc-200/80 border-zinc-700/80
Tooltip 文字 text-zinc-900 text-zinc-100

检查清单

  • 使用 [...array].reverse().map() 反转渲染顺序
  • 由渲染索引计算卡片索引:arr.length - 1 - renderIndex
  • z-index 随卡片索引递减:arr.length - cardIndex
  • 悬停时不改变 z-index
  • 悬停只应用 translateY,不使用 scale
  • Tooltip 作为兄弟元素渲染在卡片循环之外
  • Tooltip 设置 pointer-events-none 以避免悬停干扰
  • 视图切换时清除悬停状态
  • 容器使用 relative 并设置固定高度
  • 卡片使用 absolute left-1/2 配合计算出的 translateX

适用场景与限制

资料标明其用于专辑浏览器、卡片扇形、堆叠卡片列表等场景,基于 React 与 Next.js 实现。关于其他框架支持、浏览器兼容性、具体性能数据与授权许可,资料暂未提供。