z-index仅对position为relative、absolute、fixed或sticky的元素生效;父级创建层叠上下文会限制子元素层级范围;z-index值为无单位整数,同级元素按HTML顺序叠加。

z-index 只对定位元素生效
加了 z-index 却没效果?大概率是元素没设 position。CSS 规范明确要求:只有 position 值为 relative、absolute、fixed 或 sticky 的元素,z-index 才起作用。静态定位(position: static,也就是默认值)或浮动(float)元素加了也白加。
常见错误现象:
- 给一个普通
<div> 直接写 <code>z-index: 999,结果被后面出现的按钮盖住 - 用
float: left布局后试图靠z-index提升层级,完全无效
正确做法是先确认定位状态:
.popup {
position: absolute;
z-index: 1000;
}
父级创建层叠上下文会截断 z-index
子元素的 z-index 不是全局比大小,而是受限于父级是否创建了新的层叠上下文。一旦父级有以下任一条件,它的子元素就只能在“这个父级内部”比高低,无法越过它去和外部兄弟元素争层级:
-
position不是static且设置了z-index(哪怕只是z-index: 0) -
opacity小于 1 -
transform不是none -
will-change指定了影响层叠的属性 -
filter不是none
典型场景:模态框(.modal)里有个下拉菜单(.dropdown),明明 .dropdown 的 z-index 设得比 .modal 高,却还是被遮住——因为 .modal 自身已触发层叠上下文,它的子元素再高也出不去。
z-index 数值没有单位,也不支持 auto(除初始值外)
z-index 的值只能是整数(正、负、零),后面不跟 px、em 之类单位;写成 z-index: 10px 会被浏览器直接忽略。
虽然规范里初始值是 auto,但实际开发中几乎不用它来“动态计算”,因为:
-
auto表示该元素不创建新层叠上下文,且自身层级由其所在层叠上下文决定 - 你没法靠
auto让它“自动比兄弟高”,它只老老实实按文档流顺序叠放 - 绝大多数可控场景都直接写数字更可靠
别为了“语义化”写 z-index: auto,真需要重置就用 z-index: 0 或干脆删掉该声明。
多个同级元素 z-index 相同时,谁在上面看 HTML 顺序
如果两个同级定位元素都设了 z-index: 10,浏览器不会报错或随机选,而是严格按它们在 index.html 中的 DOM 出现顺序渲染:后写的那个盖在先写的那个上面。
这容易被忽略的点是:
- JS 动态插入的元素,即使
z-index和已有元素相同,也会因插入时机晚而自然在上层 - 使用
display: none隐藏的元素不参与层叠计算,但一旦显示,仍按原始 HTML 位置参与排序 - 不要依赖“写了高数值就一定赢”,得同时检查是否同层、是否被父级截断、是否 DOM 顺序不利
真正难调的层级问题,往往卡在层叠上下文嵌套和 DOM 结构上,而不是数字写小了。











