z-index失效主因是层叠上下文隔离,而非数值不足;opacity

z-index 冲突不是数值不够大,而是你试图让两个“不在同一个世界”的元素比高低——浏览器压根不让你跨层叠上下文比较。
为什么 z-index 写了却像没写一样
最常见现象:z-index: 9999 的下拉菜单总被 z-index: 10 的 header 盖住。这不是数值小,而是菜单的父容器(比如带 opacity: 0.99 或 transform: translateZ(0) 的卡片)已创建新层叠上下文,菜单的 z-index 只在该卡片内部生效。
快速验证方法:
- Chrome DevTools 选中被遮元素 → «Computed» 面板查
z-index,若显示为not applicable或灰显,说明它根本没参与层叠计算 - 再点父节点 → «Layout» 标签页看 «Stacking context» 是否为
Yes;第一个标为Yes的就是“结界源头” - 临时注释掉父级的
transform、opacity或filter,遮挡立刻消失——这就是实锤
哪些属性会静默创建层叠上下文
这些样式看着无害,但只要偏离默认值,就强制生成独立层级空间:
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括transform: scale(1)、translateZ(0)、rotate(0.0001deg)) -
filter不为none(哪怕filter: blur(0)) -
will-change: transform或will-change: opacity isolation: isolate-
position: fixed或sticky且z-index不是auto -
z-index: 0(注意:它会创建新上下文,而z-index: auto不会)
修复的关键不是堆数字,而是提级或绕开
子元素再怎么调 z-index,也破不了父级的“结界”。必须从结构层面解决:
- 如果父容器的
transform或opacity非必需(比如只为触发硬件加速),直接删掉——最干净 - 如果必须保留(如淡入动画),就把需要浮出的元素(如
dropdown、modal)用 JS 移到document.body下,配合position: fixed手动定位(别忘了监听scroll和resize更新位置) - 更可控的做法:给那个触发上下文的父容器自身设高
z-index(比如z-index: 105),让它整体抬高,而不是在内部疯狂堆z-index: 9999 - Tailwind 用户注意:
zIndex必须在tailwind.config.js中以对象语法定义(如{ 'modal': '60' }),改完要重启 dev server;z-[999]动态拼接在构建时不会被扫描
移动端和 iframe 的特殊限制
iOS Safari 对 body 和 html 极其敏感:html { transform: translateZ(0) } 这种写法会在整个页面顶层建一个强上下文,把所有后续 z-index 全锁死在里面。iframe 内部的层叠上下文完全独立于外层,z-index 数值再大也无法穿透 iframe 边界——想让弹窗盖住 iframe?只能把弹窗 DOM 挂到 iframe 外的 document.body 下。
真正容易被忽略的是:isolation: isolate 本身不提升层级,只划边界;它必须和 position + z-index 同时存在才起作用,而且加错父级等于白加。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











