Safari 在 3D 变换中无视 z-index 是因严格遵循规范:启用 3D 上下文且祖先无 overflow 时,强制按真实 z 坐标排序;修复首选 overflow: hidden(加在最近非 body 祖先),或用 translateZ() 手动调控深度,并确保 backface-visibility: hidden 和 transform-style: preserve-3d 显式声明。

z-index 在 Safari 的 3D 变换中根本不会按预期工作——这不是 bug,是它严格遵循规范的结果。你调 z-index: 9999,但只要父链里有 transform-style: preserve-3d 或没设 overflow,Safari 就直接扔掉 z-index,改用真实 3D 坐标排序。
为什么 Safari 会无视 z-index?
Safari(尤其 iOS 15–16)对 3D 渲染的校验比 Chrome 严得多:一旦容器启用了 3D 上下文(比如设了 perspective 或 transform-style: preserve-3d),且其祖先没有 overflow: hidden/scroll/auto,它就彻底放弃 z-index,只按变换后最终的 z 值决定前后关系。
常见触发场景包括:
- 给弹窗 wrapper 加了
transform: rotateY(10deg),但父级没设overflow - 用
transform-style: preserve-3d做翻转卡片,却漏掉了某个中间容器的transform-style声明 - 微信内置浏览器(iOS)沿用 Safari 渲染引擎,同样受影响
加 overflow: hidden 真的能修好?
能,而且是最小侵入、最稳的解法——overflow: hidden 会强制 Safari 回退到传统层叠模型,让 z-index 重新生效。
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
立即学习“前端免费学习笔记(深入)”;
但要注意:
- 必须加在「3D 变换元素的最近非 body 级祖先」上,不能加在 body 或太外层 layout 容器上
- 如果该祖先本身需要滚动,改用
overflow: auto或scroll同样有效 - 加了之后若内容被意外裁剪,说明该容器本就不该有溢出限制,这时得换方案
不想加 overflow 怎么办?
可以用 translateZ() 手动干预深度排序,但必须对准“谁在前”的物理逻辑,而不是瞎堆数值:
- 把想盖住别人的元素(比如遮罩层)加上
transform: translateZ(1px) - 把想被盖住的 3D 元素(比如旋转卡片)加上
transform: translateZ(-1px) - 避免用大数值如
translateZ(1000px),Safari 对极值敏感,容易抖动或失效 - 每个参与 3D 变换的子元素都得加
backface-visibility: hidden,否则遮挡计算会错乱
最容易被忽略的兼容细节
真机调试时,这几个点不检查,90% 的修复都会白做:
- iOS Safari 会为
position: fixed元素自动创建层叠上下文——别把isolation: isolate和fixed套在一起用 - 框架组件(如 Ant Design Vue、Vant)内部常带
transform或opacity,它们可能已经悄悄建了“结界”,子组件再调z-index也没用 -
transform-style: preserve-3d必须显式写在每一层父容器上,CSS reset 或 UI 库样式可能把它重置成flat,DevTools 里看不到警告,只默默退化

















