在过去,如果你想做一个鼠标悬停触发"卡片翻转"的 3D 动效(比如正面显示单词、翻转后显示释义的记忆卡片),或者一个精致的登录/注册界面的面板切换,通过纯 CSS 3D 变换来实现,你大概率遇到过这样的诡异现象:
你的卡片翻转的时候,透过表面隐约能看到背面的内容在同时出现——好像整张卡变成了"透明的"!
甚至在某些浏览器上,翻转动画还会伴随令人不适的闪烁——卡片先消失,然后背面才冒出来,整个过程毫无打磨感可言。
罪魁祸首,正是你没有正确地设置 backface-visibility。
在 CSS 的 3D 坐标系里,一个元素不仅有正面,也有背面。默认情况下,当一个元素被旋转超过 90 度、背对着用户的时候,浏览器仍然会把它渲染出来并展示给用户看——只不过是以正面的镜像形式(左右翻转)呈现的。
这个默认的"背面透视"行为,在只有单层的简单翻转中,就是卡片翻转到一半时看起来像镜面反射的根源。而在双面卡片中(正面是一个元素,背面是另一个叠放在上面的元素),正/背两张面如果同时渲染,就会出现重叠,这也就是"闪烁"的来源。
backface-visibility 就是那把开关backface-visibility 属性提供了控制这个行为的开关,它的两个值意义清晰明了:
visible(默认值):元素的背面朝向观察者时,依然渲染并显示(就是正面的镜像)。hidden:元素的背面朝向观察者时,直接隐藏,变得透明不可见。通过把正面卡片和背面卡片各自都设置为 backface-visibility: hidden,你就相当于告诉浏览器:
两张面,在任何时刻,只显示其中一张。完美!
光看原理不够,我们直接来个可以手动触发的互动 Demo:
想要实现完美的 3D 卡片效果,以下三个 CSS 属性必须协同配合:
| 属性 | 写在哪里 | 作用 |
|---|---|---|
perspective: 600px | 父容器(.scene) | 设置观察者与 3D 渲染平面的距离,值越小透视效果越夸张 |
transform-style: preserve-3d | 卡片容器(.card) | 构建 3D 渲染空间,让子元素的正/背面分布在真正的三维坐标中,而非被打平 |
backface-visibility: hidden | 正/背两张面元素 | 当自己的背面朝向用户时,主动消失 |
⚠️ Browser 兼容性提示:在某些 Safari 版本下,需要同时加上
-webkit-backface-visibility: hidden前缀前缀来确保效果正常。
Q:backface-visibility 是什么属性?它解决了什么问题?
回答思路:
backface-visibility 是一个 CSS 3D 属性,用于控制当一个 3D 旋转的元素背面朝向观察者时,该元素是否应该被渲染和展示。默认值 visible 表示依然渲染,hidden 表示直接隐藏。rotateY(180deg) 扭到后方。如果两者都不设 hidden,在翻转动画进行到一半的时候,背对着用户的那一张面依然会被渲染并透视显示,从而造成重叠和闪烁。perspective 来定义透视焦距,以及在卡片包裹容器设置 transform-style: preserve-3d 来真正激活三维渲染空间。三者缺一不可。