z-index生效需同时满足两个前提:元素必须是定位元素(position非static),且处于同一层叠上下文中;否则即使数值很大也无法跨上下文生效。

z-index 不是“设了就生效”的开关,它只在特定条件下起作用:元素必须是定位元素,且处于同一个层叠上下文(stacking context)中。否则,再大的数值也盖不住兄弟容器里的一个 z-index: 1。
为什么设置了 z-index 却不生效?
最常见原因不是值写小了,而是父级悄悄创建了新层叠上下文,把子元素“关进去了”。比如:
-
opacity: 0.99、transform: translateY(0)、filter: blur(1px)都会触发新上下文 -
position: relative+z-index: auto不创建上下文;但z-index: 0就会 - Chrome 开发者工具的 “Layers” 面板能直接标出谁创建了上下文(右键检查元素 → More Tools → Layers)
z-index 生效的两个硬性前提
缺一不可:
- 元素必须有
position值为relative、absolute、fixed或sticky——position: static下z-index完全被忽略 - 该元素必须实际参与堆叠计算:对
relative元素,哪怕只是加个top: 0或transform: translateX(0),也能确保它被当作定位盒处理
注意:z-index: auto 和 z-index: 0 表面效果相似(都让元素层级为 0),但后者会创建新上下文,前者不会。
跨容器控制层级:别靠子元素硬刚
当两个元素分属不同父容器(如一个在 .header 里,一个在 .modal 里),它们的 z-index 不可直接比较。此时真正起作用的是两个父容器自身的层叠顺序:
- 先比父容器所在上下文的层级(比如谁的父级
z-index更高) - 再比父容器自身在该上下文中的
z-index值 - 子元素的
z-index只在自己父容器内部有效
例如:.modal 的 z-index: 200,但它父级 .app 的 z-index: 100;而 .tooltip 父级是 body(根上下文),z-index: 300 —— 此时 .tooltip 一定在 .modal 上方,不管它自己设多少。
维护友好型层级设计
避免用 z-index: 9999 这类魔法数字。真实项目中建议:
- 用 CSS 自定义属性统一管理:
--z-base: 0、--z-modal: 100、--z-toast: 300、--z-devtools: 999 - React/Vue 中 Portal 渲染的弹窗默认挂载到
body,需和主应用共享同一套变量,否则极易出现“数值更大却被盖住” - Flex/Grid 容器内,子项的
z-index仅影响彼此之间顺序;若想让它压住容器外的兄弟块,必须提升到共同祖先层级操作
真正难的不是写对一个 z-index,而是看懂当前 DOM 树里到底有几个层叠上下文、谁在谁里面、谁又在哪个上下文里被“锁死”了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











