z-index不生效的主因是父容器创建了stacking context,使子元素z-index仅在局部生效;opacity、transform等属性会触发该context,需用开发者工具检查并调整层级策略。

z-index 不生效?先确认元素是否创建了 stacking context
很多情况下 z-index 看似写了却没用,根本原因不是写错了值,而是父容器悄悄创建了新的 stacking context,把子元素“锁”在局部层级里。比如 opacity: 0.99、transform: translateZ(0)、will-change: transform、filter: blur(1px) 这些属性都会触发新 stacking context —— 它们本身不显眼,但会让子元素的 z-index 只在该容器内比较,不再和页面其他元素竞争。
实操建议:
- 用浏览器开发者工具的「Layers」面板(Chrome)或「3D View」(Firefox)直观查看 stacking context 的嵌套结构
- 检查目标元素所有祖先节点的 computed styles,重点搜
opacity、transform、filter、isolation、position: fixed/sticky - 若需全局层级控制,尽量避免在中间容器上加触发 stacking context 的属性;必须加时,把
z-index提到该容器本身,而非它的子元素
relative/absolute/fixed 元素的 z-index 是怎么比的?
z-index 只对定位元素(position 为 relative、absolute、fixed 或 sticky)有效。但它们的层级不是简单按数字大小排,而是先按 stacking context 分组,再在组内比 z-index 值。
常见错误现象:两个 position: absolute 元素,一个 z-index: 100,另一个 z-index: 1,但后者反而盖在上面 —— 很可能前者父容器是普通 div(无 stacking context),后者父容器有 opacity: 0.99(创建了新 stacking context),而这个容器本身的 z-index 是 10,高于前者所在 context 的默认层(0)。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 不要只看子元素的
z-index,要查它所属的 stacking context 根节点的z-index - 同级定位元素之间才直接比
z-index;跨 context 时,比的是 context 根的层叠顺序 -
z-index: auto和z-index: 0效果不同:auto不创建 stacking context,0会(只要元素已定位)
modal 遮罩层被 iframe 或 video 盖住?这是浏览器历史遗留行为
某些嵌入内容(如 <iframe></iframe>、<video></video>、<select></select>)在旧版浏览器(尤其 IE 和早期 Chrome)中属于“操作系统级窗口”,天然处于最高 stacking level,z-index 无法压制。现代浏览器已大幅改善,但仍有边界情况。
使用场景:弹窗遮罩(z-index: 9999)挡不住嵌在页面里的 YouTube <iframe></iframe>,或全屏 <video></video> 播放时遮罩消失。
实操建议:
- 给
<iframe></iframe>加allow="autoplay; fullscreen"并确保其z-index小于遮罩容器(注意:iframe 自身不响应z-index,但它的容器可以) - 视频元素可临时设
visibility: hidden或display: none在 modal 打开时(需监听状态) - 避免依赖纯 CSS 层级压制这类内容;必要时用 JS 控制生命周期(如 modal 显示前 pause 视频、移除 iframe)
移动端 iOS Safari 的 z-index 异常表现
iOS Safari(尤其 15.x 之前)对 stacking context 的处理更敏感,常见问题包括:fixed 定位导航栏在滚动时突然被内容穿透、键盘弹出后 z-index 重排、transform + z-index 组合失效。
性能 / 兼容性影响:iOS 上频繁创建 stacking context(比如每个列表项都加 transform: translateZ(0))会显著增加图层合成压力,导致滚动卡顿。
实操建议:
- 避免在滚动区域内部元素上滥用
transform或will-change;如需硬件加速,优先加在滚动容器本身 - 固定定位元素(如 header)务必设置
z-index,且其父容器不能有意外的 stacking context - 测试时务必真机运行,模拟器无法复现部分渲染异常
层级问题从来不是单点调整能解决的,它是整个 DOM 结构、CSS 渲染流程和浏览器实现细节共同作用的结果。最常被忽略的,其实是那个没写 position 却默默创建了 stacking context 的父 div。


















