z-index控制元素在Z轴的堆叠顺序,但其效果受堆叠上下文限制。只有定位元素(position非Static)的z-index才生效,且元素的层级比较仅在其所属的堆叠上下文中进行。根元素、设置了opacity或transform的元素等会创建新的堆叠上下文,导致内部z-index独立计算。因此,即使某元素z-index值很大,若其所在堆叠上下文层级较低,仍可能被外部小z-index但处于更高上下文的元素覆盖。常见问题如弹窗被遮挡,往往因父容器创建了新上下文所致,解决方法包括将弹窗移至body下或调整上下文结构。理解“堆叠上下文”是掌握z-index行为的关键。

在网页开发中,元素的层级显示是一个常见且关键的问题。当你需要让某个元素(比如弹窗、下拉菜单或提示框)显示在其他元素之上时,就需要用到css中的 z-index 属性。但仅仅设置 z-index 并不能保证层级生效,因为还涉及到“堆叠上下文”这一核心概念。理解 z-index 与堆叠上下文的关系,是掌握页面视觉层级控制的关键。
z-index 的基本作用
z-index 决定了定位元素在 Z 轴(垂直于屏幕的方向)上的堆叠顺序。数值越大,元素越靠前。它只对定位元素有效,也就是 position 值为 relative、absolute、fixed 或 sticky 的元素。
注意:对 position: static(默认值)的元素设置 z-index 是无效的。
例如:
.box1 { position: absolute; z-index: 1; } .box2 { position: absolute; z-index: 2; }
此时 .box2 会显示在 .box1 之上。
立即学习“前端免费学习笔记(深入)”;
堆叠上下文:决定层级范围的“容器”
z-index 并不是全局比较的。浏览器会创建一个叫“堆叠上下文”(Stacking Context)的独立层级环境。在一个堆叠上下文中,所有子元素的 z-index 都只在这个上下文内比较。
这意味着:即使一个元素设置了 z-index: 999,如果它所在的堆叠上下文整体层级较低,它仍然可能被另一个 z-index 较小但属于更高层级堆叠上下文的元素覆盖。
以下情况会创建新的堆叠上下文:
- 根元素()自动创建根堆叠上下文
- position 不为 static 且 z-index 不为 auto 的元素
- flex 或 grid 容器的子元素,当 z-index 不为 auto 时
- opacity 小于 1 的元素
- transform 不为 none 的元素
- Filter 不为 none 的元素
- will-change 设置了影响堆叠的属性(如 transform、opacity)
- mix-blend-mode 不为 normal 的元素
- isolation: isolate 的元素
堆叠顺序规则:谁在最上面?
在同一个堆叠上下文中,元素按照以下顺序从下到上排列:
- 背景和边框(z-index: auto 或 0 的块级元素)
- z-index 为负数的定位元素(如 z-index: -1)
- 非定位的行内元素和浮动元素
- z-index 为 auto 或 0 的定位元素
- z-index 为正数的定位元素(数值越大越靠上)
这个顺序说明:负 z-index 元素会显示在普通内容之下,而正 z-index 元素则浮在最上方。
常见问题与解决方案
开发者常遇到“设置了 z-index 却没效果”的问题,通常是因为堆叠上下文的限制。
示例场景:一个 modal 弹窗被页面中的 banner 图片遮挡,尽管 modal 的 z-index 更高。
原因可能是:banner 所在的父容器使用了 transform: translateY(0) 或 opacity: 0.99,这会创建一个新的堆叠上下文,导致其内部元素整体层级提升,覆盖了外部 modal。
解决方法:
- 确保 modal 处于一个足够高的堆叠上下文中
- 将 modal 移至 body 下作为顶层元素(推荐做法)
- 检查并调整父级元素是否无意中创建了高优先级的堆叠上下文
基本上就这些。掌握 z-index 的关键是理解它不是孤立起作用的,而是依赖于堆叠上下文的层级结构。不复杂但容易忽略。