z-index不生效的根本原因是元素未进入层叠计算流程:必须是非static定位(如position: relative)、实际重叠(grid-column/row或grid-area一致)、未被父级层叠上下文隔离(无opacity

Grid 重叠元素的 z-index 不生效,不是代码写错了,而是它根本没进入层叠计算流程——position 还是 static,或者被父级“关进了独立盒子”。
为什么写了 z-index 却完全没反应
浏览器对 z-index 的处理有硬性前提:元素必须是非 static 定位。Grid 子项默认就是 position: static,此时无论你写 z-index: 9999 还是 z-index: -1,Computed 面板里都会显示为 auto,且不参与任何层叠排序。
- 用 DevTools 的 «Computed» 面板直接搜
position,确认值不是static - 最稳妥的激活方式是加
position: relative——它不脱离 Grid 轨道,grid-column和grid-row依然有效 - 别用
position: absolute单纯为了启用z-index,否则元素会脱离网格定位,grid-column: 2 / 3等设置直接失效
重叠本身没做对,z-index 就无从谈起
视觉重叠不是靠 z-index “拉出来”的,而是靠网格定位把多个元素塞进同一区域。如果它们根本没占同一格,z-index 再高也盖不到对方头上。
- 合法重叠写法:
grid-column: 2 / 3; grid-row: 1 / 2(明确占据第 2 列第 1 行) - 危险写法:
grid-column: 2 / 2(宽度为 0,元素不可见)或只写grid-column: 2(等价于2 / 3,但易误判实际跨度) - 用命名区域时,确保多个元素共用同一
grid-area,比如都设grid-area: "hero" - 调试技巧:DevTools 勾选 “Show grid areas” 和 “Show line numbers”,一眼看清是否真重叠
父容器悄悄创建了层叠上下文,子项 z-index 被锁死
即使 position 和 grid-column 都对了,z-index 仍可能被截断在局部范围内。只要某个祖先元素满足以下任一条件,它就创建了新的层叠上下文(stacking context),子项的 z-index 只能在这个“小房间”里比大小:
-
opacity小于 1(哪怕只是opacity: 0.99) -
transform不为none(包括transform: translateZ(0)、scale(1)) -
filter不为none(哪怕filter: blur(0)) -
will-change或isolation: isolate
验证方法:DevTools 的 «Layout» 面板中逐级点击父节点,看 «Stacking context» 是否突然变成 Yes;临时注释掉可疑属性,遮挡关系是否立刻恢复。
跨 Grid 容器重叠时,z-index 天然不互通
两个元素分属不同 display: grid 容器时,它们的 z-index 完全无关。例如卡片里的图标设了 z-index: 999,弹窗在另一个 Grid 容器里,图标永远盖不过弹窗——因为它们不在同一个层叠上下文中。
- 解决路径不是堆高子项数值,而是提升共同祖先的
z-index - 常见陷阱:父容器带
opacity: 0.99或transform,意外创建了隔离上下文,导致子项层级无法穿透 - 移动端 Safari(iOS 15.4 之前)对
translateZ(0)更敏感,容易引发层级错乱,无法通过 CSS 规避,需降级为position: fixed+ JS 同步位置
真正难的不是算清该写多少,而是每次改完样式,都要往上多看两层 DOM,确认那个刚被激活的 transform 或 opacity 没把你需要突出的元素关进盒子。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











