z-index仅对定位元素生效,必须配合position: relative/absolute/fixed/sticky使用;static元素忽略z-index,transform等属性虽创建层叠上下文但不赋予z-index排序权。

z-index 不是“层级开关”,而是“层叠上下文内的排序指令”——它只在已存在的层叠上下文中起作用,而定位(position)是创建该上下文的最直接、最可控方式。
z-index 只对定位元素生效,这是 CSS 规范强制要求
浏览器渲染时,会为每个元素分配一个“层叠水平(stacking level)”,这个水平由元素类型和样式共同决定。普通流内元素(position: static)默认处于“文档流层叠层”,z-index 在这里完全被忽略——开发者工具里该属性会置灰,hover 提示明确写着 “z-index has no effect on non-positioned elements”。
只有当 position 设为 relative、absolute、fixed 或 sticky 时,元素才被标记为“已定位”,从而获得参与更高一级层叠排序的资格。
- 设
position: relative是最轻量的选择:不脱离文档流,仅激活z-index权限 - 设
position: absolute或fixed同时带来脱离文档流 + 触发层叠上下文(尤其fixed默认进入根层叠上下文) - 千万别用
position: static混搭z-index—— 它永远无效,且容易掩盖真正的问题
不加定位时 z-index 失效的典型现象
你给按钮写了 z-index: 9999,但它依然被背景视频盖住;你给弹窗设了 z-index: 100,却卡在导航栏下面——这些都不是数值不够大,而是按钮/弹窗本身还没“入场”。
立即学习“前端免费学习笔记(深入)”;
常见错误组合:
-
div { z-index: 100; }→ 无效,position缺失 -
button { z-index: 200; opacity: 0.99; }→ 仍无效,opacity < 1虽能创建层叠上下文,但不会让z-index生效(它只是改变了该元素的层叠上下文“入口权限”,而非“排序权限”) -
img { position: relative; z-index: 1; }→ 有效,但若父容器有transform或opacity,子元素的z-index就只能在父级上下文内比较
为什么不用其他属性替代定位来启用 z-index?
某些样式属性(如 transform、opacity、filter)确实也能创建新的层叠上下文,但它们不赋予元素“z-index 排序权”。也就是说:
-
transform: translateZ(0)让元素变成层叠上下文根,但它自身仍按“默认层叠水平”排位(等价于z-index: auto) -
opacity: 0.99同样创建上下文,但子元素的z-index仍受限于该上下文边界,且父元素自身无法靠z-index抬升 - 只有
position+ 显式z-index的组合,才能同时满足“进入上下文”和“在其中排序”两个条件
实际调试建议:三步定位 z-index 失效根源
遇到层级错乱,别急着调大数值,先检查链路:
- 目标元素是否设置了
position?值是不是static?(用开发者工具看 computed 样式里的position) - 它的父元素是否无意中创建了层叠上下文?比如用了
transform、opacity < 1、或设置了z-index(哪怕为0)? - 对比元素是否属于同一层叠上下文?如果不是,
z-index数值再大也跨不出父级边界——这时要调整的是父级的层叠顺序,而不是子元素
最常被忽略的一点:z-index: auto 和 z-index: 0 表面效果相似,但后者会创建新层叠上下文,前者不会。混用它们会让层叠结构变得不可预测。


















