纯 css 无法实现真正可用的探探式卡片堆叠效果,必须用 js 动态控制 z-index 和 transform;因静态 z-index 无法响应交互重排、尺寸变化及父容器隔离问题,且卡片需 absolute 定位配合 relative 容器与实时 transform 偏移才能精准叠层。

纯 CSS 实现不了真正可用的探探式卡片堆叠效果——必须用 JS 动态控制 z-index 和 transform,否则滑动、回弹、层级重排全会失效。
为什么 position: relative + nth-child 写死 z-index 就崩
很多人照着教程写:.card:nth-child(1) { z-index: 1; top: 0; }、.card:nth-child(2) { z-index: 2; top: -8px; }……这在静态页面里看似能堆起来,但一交互就露馅:
- 滑动移除顶部卡片后,第二张不会自动“升顶”——
z-index是静态规则,浏览器不会重算 DOM 序号 - 用户缩放字体或图片加载完成,卡片高度变化,
top: -8px就错位,堆叠基线漂移 - 移动端横竖屏切换,硬编码的偏移值完全不适应容器宽度变化
-
z-index在不同父容器中互不感知:如果某张卡被包进一个position: relative的.featured-wrapper里,它的z-index: 99只在该 wrapper 内有效,压不住同级其他卡片
真正起作用的定位组合是 absolute + relative 容器 + JS 驱动
所谓“用 relative 实现堆叠”,只是初学者误读。探探式效果的底层结构必然是:
- 父容器设
position: relative,作为所有卡片的定位参考系 - 每张卡片设
position: absolute,且统一top: 0、left: 0起始位置 -
z-index值由 JS 按当前可视顺序实时注入(例如顶层卡style.zIndex = "10",下一张"9") - 偏移靠
style.transform = "translateX(24px) translateY(-12px) scale(0.96)",不是top/left
关键点:position: relative 在这里只服务于父容器,不是给卡片用的;卡片必须 absolute 才能精准叠在同一视觉锚点上,否则文档流残留会导致滑动错帧。
z-index 数组不是 CSS 类名,而是运行时状态映射
所谓“z-index 数组”,指的是 JS 中维护的一个整数序列,比如 [10, 9, 8, 7],它和 DOM 顺序严格一一对应,并随操作实时重排:
- 用户左滑移除第一张 → 数组变为
[9, 8, 7]→ JS 批量更新剩余卡片的style.zIndex - 不能只改被滑动那张的
z-index,否则下一张仍卡在z-index: 2,被后面更高值的卡片盖住 - 避免用
z-index: 9999这类魔数——留出余量(如最大用到 50),方便后续插入动画层、tooltip、loading overlay 等
移动端 touchmove 中位移计算和防抖关键点
手指一动就卡顿或跳变,90% 出现在 touchmove 处理逻辑里:
- 记
startX = e.touches[0].clientX,不存pageX(受滚动影响) -
touchmove中只算dx = e.touches[0].clientX - startX,直接赋给顶层卡片的style.transform,不做任何 DOM 查询或setState - 必须调
e.preventDefault(),尤其在 iOS 微信和 Safari 中,否则默认滚动会抢事件 - 别用
style.left或style.marginLeft——它们和transform不兼容,会导致回弹错位
最易被忽略的是:所有卡片的 z-index 必须由 JS 在每次滑动后**立即重排**,不能依赖 CSS 规则顺序;而 transform 偏移量要随索引差值线性递增(如第 i 张比当前顶卡低 2 层,就 translateX(8px) translateY(-6px)),否则堆叠角度会随数据长度变化而突变。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











