z-index不生效主因是元素未脱离文档流,须设position为relative/absolute/fixed/sticky;若父元素创建了层叠上下文(如opacity<1),子元素z-index仅在该上下文中生效。

z-index 不生效?先检查元素是否脱离文档流
绝大多数 z-index 失效问题,根本原因不是值设得不够大,而是目标元素没有定位属性。z-index 只对「定位元素」起作用——也就是 position 值为 relative、absolute、fixed 或 sticky 的元素。
常见错误现象:z-index: 9999 写了但完全没反应;父容器遮住了子元素,调高子元素 z-index 也无效。
- 必须显式设置
position,哪怕只是position: relative(不改变布局也能激活z-index) - 父级若也有
position且设置了z-index,子元素的层级只在该父级的层叠上下文中生效,不会突破出去 -
position: static(默认值)下,z-index完全被忽略,浏览器直接当不存在
为什么设了 position 和 z-index 还是被盖住?看层叠上下文
层叠上下文(stacking context)是理解 z-index 行为的关键。它像一层透明胶片,内部元素的 z-index 只在本胶片内排序,胶片之间按创建顺序或 z-index 值整体叠加。
容易踩的坑:给弹窗加 z-index: 1000,结果被一个 opacity: 0.99 的父容器挡住——因为 opacity 小于 1 会触发新层叠上下文。
立即学习“前端免费学习笔记(深入)”;
- 以下 CSS 属性会创建新的层叠上下文:
opacity(transform(非 none)、filter(非 none)、will-change、perspective等 - 一旦父容器创建了层叠上下文,子元素再高的
z-index也无法超过该容器在外部上下文中的层级 - 调试建议:用浏览器开发者工具的「Layers」面板(Chrome)或「Computed」中查看
stacking context是否意外生成
让元素「始终」在顶层?别只靠 z-index 数值堆砌
硬写 z-index: 2147483647 并不能保证“始终顶层”,反而可能引发后续维护冲突。真正可控的做法是控制层叠上下文的结构和层级锚点。
典型使用场景:全局提示框(Toast)、模态框(Modal)、悬浮按钮(Fab)。
- 为不同功能类型预设层级范围,例如:
--z-toast: 1000、--z-modal: 1050、--z-overlay: 1040,用 CSS 自定义属性统一管理 - 确保关键浮层的父容器本身不被意外创建层叠上下文(比如避免给
.modal-wrapper加opacity或transform) - 如果依赖 JS 动态插入元素(如第三方 SDK 的提示框),需检查它是否自带
position和z-index,必要时用!important覆盖(慎用,仅兜底)
移动端和 Safari 的 z-index 兼容性注意点
Safari(尤其 iOS)对层叠上下文更敏感,某些组合下 z-index 表现和 Chrome 不一致,不是 bug,而是规范实现更严格。
常见问题:position: fixed 元素在 iOS 上被 overflow: hidden 父容器裁剪,或层级错乱。
- iOS Safari 中,
transform: translateZ(0)或will-change: transform可能意外提升元素层级,但也可能创建新层叠上下文,需实测 - 避免在
body或根容器上设置overflow: hidden+position: relative,这在 Safari 中极易导致 fixed 元素层级异常 - 如果使用
backdrop-filter,它会强制创建层叠上下文,此时其子元素的z-index需要相对于 backdrop 本身来设计


















