z-index不生效的根本原因是元素未进入层叠上下文,必须为定位元素(position非static)且父级未意外创建隔离上下文;层级比较按上下文逐级进行,而非全局数值大小。

z-index 不生效?先确认元素是否脱离了普通文档流
很多情况下 z-index 看似“没用”,其实是因为目标元素根本没进入层叠上下文(stacking context)——它只对定位元素(position 值为 relative、absolute、fixed 或 sticky)起作用,对 static 元素完全无效。
- 检查目标元素的
position是否被设为static(默认值),如果是,必须显式改成其他值才能启用z-index - 父容器若设置了
transform、filter、opacity 或 <code>will-change,也可能意外创建新的层叠上下文,把子元素的z-index限制在该局部范围内 - 浏览器 DevTools 的“Layers”面板(Chrome)或“Computed”中的
z-index行变灰/不可编辑,通常意味着该元素未参与层叠上下文
多个 z-index 值冲突时,谁说了算?
层级不是全局数字比大小,而是按层叠上下文逐级计算。父级的 z-index 决定了整个子树的“入场券等级”,子元素再高的 z-index 也跨不出父级划定的层叠范围。
- 如果 A 元素
z-index: 10,B 元素在另一个独立层叠上下文中且z-index: 999,但它的父容器z-index: 1,那 B 依然压不住 A - 常见陷阱:模态框(modal)里嵌了个
position: absolute的下拉菜单(dropdown),结果菜单被 modal 的遮罩层盖住——因为 modal 容器本身已建了上下文,而 dropdown 没提升其父级的z-index - 用 DevTools 逐层点开父节点,看哪一级的
z-index实际影响了当前元素的渲染顺序
fixed / absolute 元素重叠,z-index 失效的典型场景
当两个 position: fixed 元素同级存在,且都未设置 z-index,它们会按 HTML 出现顺序堆叠(后写的在上)。一旦加了 z-index,就进入层叠上下文比较逻辑;但若其中一个父级有 transform,就可能切出新上下文,导致数值对比失效。
- 导航栏
position: fixed; z-index: 100,通知气泡position: fixed; z-index: 200,但气泡总被遮住 → 检查通知气泡是否被包在某个带transform: translateZ(0)的 wrapper 里 -
z-index只接受整数,不支持小数或单位(如z-index: 1.5或z-index: 10px),写错会导致该声明被浏览器忽略 - 避免无意义的高数值(如
z-index: 999999),不同模块间应约定好层级区间(例如:header=100, toast=200, modal=300, overlay=400)
移动端 Safari 中 z-index 表现异常怎么办?
iOS Safari 对层叠上下文更敏感,尤其涉及 transform、backface-visibility 或 -webkit-overflow-scrolling: touch 的容器,容易意外触发新上下文或重排规则。
立即学习“前端免费学习笔记(深入)”;
- 在 iOS 上下拉刷新区域(
body或html设置了overscroll-behavior: contain)中,fixed元素可能被截断或层级错乱 - 尝试给父容器加
transform: translateZ(0)强制创建层叠上下文,有时反而能统一行为(但慎用,可能影响滚动性能) - 用
will-change: transform替代盲目加transform,减少副作用;同时确保z-index配套设置在同级定位元素上
z-index 数值本身,而是你没意识到它正被哪个看不见的层叠上下文悄悄截断。










