perspective属性必须设在父容器上且子元素启用transform-style: preserve-3d才生效,直接加在动效元素上无效;正确结构是父容器设perspective和preserve-3d,子元素仅用transform;移动端safari不支持body/html上的perspective,需显式包裹容器。

直接给要动的元素加 perspective 属性,99% 情况下没效果——它必须设在父容器上,且子元素得启用 transform-style: preserve-3d,否则所有 3D 变换都会被拍平成 2D。
perspective 必须作用在父容器上
这是最常踩的坑。很多人写:
.box { perspective: 1000px; transform: rotateY(45deg); }
完全无效。因为 perspective 不是变换函数,它定义的是「观察者到 z=0 平面的距离」,只对设置了 transform-style: preserve-3d 的**直接子元素**生效。
- 正确结构是:外层容器(如
.scene)设perspective和transform-style: preserve-3d - 子元素(如
.box)只负责transform,比如rotateY(45deg)或translateZ(200px) - 移动端 Safari 对
body或html上的perspective支持不稳定,务必用显式包裹容器
perspective 值怎么选:200px 到 1200px 是安全区间
数值越小,透视感越强,但容易失真;越大越“平”,接近正交投影。实际选值要看元素尺寸和动效意图:
- 卡片翻转、按钮悬停:推荐
600px–800px,自然不夸张 - 全屏 3D 场景(如立方体):
1000px–1200px更稳妥 - 避免用
50px或5000px——前者边缘拉伸严重,后者几乎看不出深度 - 注意单位必须带
px(或em等长度单位),perspective: 1000无效
为什么 translateZ 没反应?先查 preserve-3d 和层叠上下文
写了 transform: translateZ(100px) 却没前后变化,大概率不是代码写错,而是渲染上下文断了:
- 父容器漏了
transform-style: preserve-3d,子元素默认被拍平 - 父容器有
overflow: hidden、opacity: 0.99、filter: blur(1px)等属性,会意外触发新层叠上下文,中断 3D 渲染链 -
backface-visibility: hidden虽然常用于翻转效果,但如果误加在父容器上,也可能干扰子元素的 Z 轴可见性
perspective() 函数 vs perspective 属性:别混用
perspective() 是 transform 函数之一,可写在单个元素上,比如:
.box { transform: perspective(1000px) rotateY(45deg); }
但它和 perspective 属性有本质区别:
-
perspective属性作用于父容器,为所有子元素提供**共享透视原点**,适合协调多个 3D 元素(如立方体六个面) -
perspective()函数作用于单个元素,每个元素都有**独立视点**,多个元素一起动时消失点不一致,容易显得“散” - 两者不能同时存在:如果父容器设了
perspective: 1000px,子元素再写perspective(1000px),后者会被忽略
真正难的不是写对那几行 CSS,而是理解「透视不是贴在元素身上的贴纸,而是一个空间坐标系的起点」——一旦父容器没立住这个坐标系,后面所有 rotateX、translateZ 都只是在二维平面上徒劳地画线。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











