最可控的卡片堆叠方案是用 position: relative 配合 top/left 或 transform: translateY() 微调位置,并设递增 z-index;z-index 必须与定位属性共存,hover 时需统一重置其他卡片层级。
卡片堆叠并不是依靠 position: absolute 将全部元素强行移到同一坐标;这样会让它们脱离文档流,导致后续卡片难以维护,响应式布局也容易崩溃。更稳妥的方式是让每张卡片留在普通流中,再用 position: relative 进行局部偏移。
核心在于:relative 不会影响其他元素的布局,却可以通过 top、left 细调自身位置,并配合 z-index 管理叠放次序:
position: relative(只有需要限制绝对定位子元素范围时才设置,但此处不需要)position: relative,然后分别设置递增的 z-index 以及较小的负值 top(偏移量可设为 -8px),视觉上便会呈现前一张被后一张盖住的效果top 向下移动,否则卡片会整体下沉,导致堆叠基线不稳定这是最容易遇到的问题:z-index 在 position: static(默认值)状态下完全不起作用。许多开发者为卡片设置了 z-index: 2 却没有添加 position,所以层级没有任何变化。
实际操作需要注意:
立即学习“前端免费学习笔记(深入)”;
z-index,就要同时声明 position(relative、absolute 或者 fixed)position: relative 的父容器内时,它们的 z-index 不存在全局排序,只会在所属 stacking context 中进行层级比较z-index: 1 ~ z-index: 4),不要写成 999 或者 9999,否则后期难以覆盖虽然 top 可以完成偏移,但仍会参与盒模型计算(例如影响 margin-collapse 或依据父容器高度进行判断)。从现代性与安全性考虑,则应选择 transform: translateY():
transform 动画因独立图层被触发而获得更佳性能,在 hover 动效下的流畅度尤其明显transform: translateY(-6px); 其效果与 top: -6px; 接近,但实现更简洁transform 不会影响 z-index 的排序逻辑,层级依旧由 z-index + position 决定仅给当前卡片添加 z-index: 99 仍然不够,因为其他卡片的 z-index 如果是 4、3、2,就仍有可能遮挡当前卡片。必须统一降低层级:
:hover 先让父容器进入相应状态,子项层级再由后代选择器统一重置.card-stack:hover .card { z-index: 1; },之后再为 .card:hover 设置 z-index: 10
transition: z-index 0.2s ——尽管 z-index 自身无法过渡,但结合 transform 或者 opacity 能够形成视觉缓冲stacking context 的嵌套边界才是难点——某张卡片的父元素一旦具有 opacity: 0.99 或者 will-change: transform,新的 stacking context 便可能在预料之外形成,进而使 z-index 失效。只有进入多层卡片交互动画,这类潜藏的限制往往才会显现。