先记住这个答案
transform-style 这个属性设在父元素上,决定子元素是否保留在父元素的 3D 空间里。默认值 flat 会把子元素的 3D 变换结果投影到父元素的平面上,看起来像一张贴在父元素表面的「照片」。设成 preserve-3d 之后,子元素可以在三维空间里真正前后移动、绕轴旋转,和父元素及兄弟元素产生遮挡关系。
flat把子元素压平到父元素平面,是默认值preserve-3d保留子元素的三维位置- 翻牌效果常在父级使用
preserve-3d overflow: hidden会使三维场景压平
翻牌效果必须靠 preserve-3d
翻牌是最常见的 3D 效果。一张卡片有正面和背面两个子元素,鼠标悬停时绕 Y 轴旋转 180 度。如果父元素没有设 preserve-3d,正反两面会被压平到同一个平面上,旋转时看不到「翻转」的立体感。
.card {
position: relative;
width: 200px;
height: 280px;
perspective: 800px; /* 给子元素提供透视 */
}
.card-inner {
transform-style: preserve-3d; /* 让正反面共享 3D 空间 */
transition: transform 0.6s;
position: relative;
width: 100%;
height: 100%;
}
.card:hover .card-inner {
transform: rotateY(180deg); /* 悬停时翻转 */
}
.card-front, .card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden; /* 背面不可见 */
}
.card-back {
transform: rotateY(180deg); /* 初始就翻过去 */
}.card-inner 上的 preserve-3d 是关键。去掉它改成 flat,正面和背面就会重叠在同一个平面上,完全看不到翻转效果。
哪些属性会让 preserve-3d 失效
preserve-3d 有一个容易踩的坑。某些属性会强制浏览器把元素「压平」,即使你写了 preserve-3d 也不起作用。
overflow 设成 hidden、scroll 或 auto 时,浏览器需要裁剪内容,没法保留 3D 空间,会回退到 flat。这个问题在做翻牌效果时经常碰到:给卡片容器加了 overflow: hidden 想裁掉溢出内容,结果 3D 效果没了。
opacity 小于 1 也会触发压平。浏览器在合成透明图层时需要先把内容渲染成一张 2D 位图,3D 信息就丢失了。filter(值不是 none)、clip-path、mask 也是同样的原因。
碰到 preserve-3d 不生效,先检查这个元素和它的祖先有没有设这些属性。
preserve-3d 不会自动继承
假如有三层嵌套:爷爷设了 preserve-3d,父亲没设,孙子做 3D 变换。孙子的 3D 变换不会出现在爷爷的 3D 空间里,因为 preserve-3d 不继承。3D 空间在父亲那一层就断了。
要让孙子也参与 3D 空间,每一层中间元素都要设 preserve-3d。这在做立方体或多层嵌套的 3D 布局时尤其要注意。
容易答错的地方
- 以为
preserve-3d等于perspective perspective定义观察者的距离,产生近大远小的效果。preserve-3d决定子元素是否在 3D 空间里。两个属性经常一起用,但作用完全不同。只设perspective不设preserve-3d,子元素的 3D 变换还是会被压平。- 以为设了
preserve-3d就一定有效 overflow: hidden、opacity小于 1、filter都会让preserve-3d回退到flat。写了preserve-3d不等于生效了,要用 DevTools 检查实际渲染。
面试官还会怎么问?
做一个 CSS 立方体需要哪些属性配合?
外层容器设 perspective 提供透视。中间层设 preserve-3d 让六个面共享 3D 空间。六个面分别用 rotateX、rotateY 和 translateZ 定位到正确位置。每个面都要加 backface-visibility: hidden 避免看到背面。
backface-visibility 和 preserve-3d 有什么关系?
backface-visibility: hidden 让元素旋转到背面时不可见。它必须在 preserve-3d 的 3D 空间里才有意义。在 flat 模式下,元素不会真正旋转到背面,backface-visibility 基本不起作用。
移动端做 3D 效果需要注意什么?
移动端浏览器对 preserve-3d 嵌套层数有限制,层数太深可能出现渲染异常。另外 3D 变换会触发合成层,过多合成层会占用 GPU 内存。建议控制嵌套层数,不做 3D 效果的元素不要设 preserve-3d。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。