z-index: -1 在 3d 场景中失效,因 transform 触发新层叠上下文,真正控制景深的是 translatez 数值与父容器的 perspective + transform-style: preserve-3d 配合。

z-index: -1 为什么不能让背景元素“退到后面”还保持透视效果
因为 z-index 只在同一个层叠上下文(stacking context)内起作用,而 transform: translateZ() 触发新层叠上下文的同时,会把元素“提”进 3D 渲染空间——此时 z-index: -1 失效,它只是把元素塞进父容器的负 Z 层,但父容器本身没开 3D 空间,结果就是元素直接被裁剪或不可见。
常见错误现象:background-element 消失、页面空白、开发者工具里能看到 DOM 但不渲染。
- 必须给父容器加
transform-style: preserve-3d,否则子元素的translateZ被扁平化 - 父容器还得有
perspective(比如perspective: 1000px),不然没有透视感,只有平移 -
z-index: -1在这里纯属干扰项,删掉更安全;真正控制前后关系的是translateZ的数值大小
用 transform: translateZ 实现背景景深的最小可行写法
核心不是“把背景放后面”,而是让背景和前景在同一个 3D 空间里拥有不同 Z 坐标。浏览器按 Z 值做深度合成,配合 perspective 产生远小近大效果。
使用场景:视差滚动、卡片悬浮浮出、登录页带纵深感的粒子背景。
立即学习“前端免费学习笔记(深入)”;
body {
perspective: 1200px;
}
.bg-layer {
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
transform: translateZ(-200px) scale(1.5); /* 负值越小,越“远” */
transform-style: preserve-3d; /* 必须设在有子元素需要 3D 的容器上 */
}-
scale(1.5)是补偿:Z 越负,视觉越小,需放大拉回尺寸 - 不要对
body直接设transform-style,它不接受该属性;应设在直接承载 3D 元素的父容器上 - 移动端要注意
perspective值太小会导致畸变,建议 ≥800px
fixed 定位 + translateZ 导致背景“粘不住”滚动的坑
当给 position: fixed 元素加 translateZ,某些浏览器(尤其是 Safari 和旧版 Chrome)会把它当作合成层处理,从而脱离文档流的固定锚点逻辑,滚动时出现微位移或抖动。
错误现象:滚动时背景轻微晃动、边缘露白、与前景错位。
- 解决方案:改用
position: absolute+top: 0; left: 0;,并在根容器(如#app)上设overflow: hidden - 或者保留
fixed,但加will-change: transform提前声明,减少合成策略突变 - 避免在
translateZ同时用opacity动画——两者叠加容易触发频繁重绘,尤其在低配设备上
多层 translateZ 背景的层级管理要点
多个景深背景(比如云层、山体、地面)不是靠 z-index 排序,而是靠 translateZ 数值严格递进:越接近 0 越“近”,越负越“远”。顺序错一点,视觉就穿帮。
参数差异:translateZ(-100px) 和 translateZ(-101px) 在 1200px perspective 下几乎看不出区别,但 -100px 和 -500px 就明显分层。
- 推荐用整百/整五十阶梯:-100px、-300px、-600px,便于调试和协作理解
- 所有层必须共享同一个
perspective父容器,否则各层透视中心不一致,看起来像错位镜头 - 别用
%或rem写translateZ值——它只接受px、em、vw等绝对/视口单位,%无效
复杂点在于:perspective 不是 CSS 变量可继承的属性,也不能用 calc() 动态算,每次换容器就得手动同步;最容易被忽略的是,哪怕只加一行 transform: translateZ(0),也会悄悄创建新层叠上下文——这可能意外截断你原本想透出的阴影或下拉菜单。










