backface-visibility - 背面可见性
控制元素背面是否可见
什么是 backface-visibility?
当元素通过 3D 变换旋转时,其背面可能会朝向观察者。backface-visibility 属性决定这个背面是否可见。
- 应用场景:卡片翻转、3D 立方体等需要隐藏背面的效果
- 性能优化:隐藏背面可以提升渲染性能
- 配合使用:通常与 transform-style: preserve-3d 一起使用
理解"背面"的概念
关键理解:每个 HTML 元素就像一张纸,有正面和背面。当你用
rotateY(180deg) 翻转它时,
你看到的是它的背面(就像纸翻过来,文字是镜像的)。backface-visibility: hidden
的作用就是:当背面朝向你时,让它变透明。
场景对比演示
场景 1:正常叠加
原因:两个都是 absolute,BACK 在上层覆盖了 FRONT
场景 2:BACK 翻转 180°
原因:BACK 翻转后,你看到的是它的背面(文字镜像)
场景 3:隐藏背面
原因:BACK 的背面被隐藏,露出下面的 FRONT
场景 4:完美翻转
原因:两面都隐藏背面,自动切换显示
/* 场景 1:正常叠加 - BACK 覆盖 FRONT */
.front, .back {
position: absolute;
}
/* 场景 2:BACK 翻转 - 看到镜像文字 */
.back {
transform: rotateY(180deg);
}
/* 场景 3:隐藏 BACK 的背面 - 露出 FRONT */
.back {
transform: rotateY(180deg);
backface-visibility: hidden;
}
/* 场景 4:完美翻转 - 两面都隐藏背面 */
.front, .back {
backface-visibility: hidden;
}
.back {
transform: rotateY(180deg);
}
语法说明
.element {
backface-visibility: visible | hidden;
}
- visible - 默认值,背面可见
- hidden - 背面不可见
对比演示:visible vs hidden
悬停卡片查看翻转效果
visible(默认)
❌ 翻转时两面都可见,产生重叠
hidden
✅ 背面隐藏,翻转效果完美
/* 错误:背面可见,产生重叠 */
.card-face {
backface-visibility: visible;
}
/* 正确:隐藏背面 */
.card-face {
backface-visibility: hidden;
}
示例 1:完美的卡片翻转
悬停查看翻转效果
/* 卡片容器 */
.card {
perspective: 1000px;
}
.card-inner {
transform-style: preserve-3d;
transition: transform 0.8s;
}
.card:hover .card-inner {
transform: rotateY(180deg);
}
/* 卡片两面 - 关键:隐藏背面 */
.card-face {
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
示例 2:3D 立方体
立方体的每个面都设置了 backface-visibility: hidden
观察:当某个面的背面朝向你时,它会自动隐藏,只显示正面朝向你的面
工作原理
什么是"背面"?
当元素通过 3D 旋转(如 rotateY(180deg))翻转后,原本面向观察者的"正面"会转到背后, 而原本在背后的"背面"会转到前面。backface-visibility: hidden 会让这个背面变得不可见。
- 正面:元素初始状态下面向观察者的一面
- 背面:元素旋转 180 度后,原本正面的反面
- 判断依据:元素的法线方向是否朝向观察者
使用场景
- 🃏 卡片翻转:最常见的应用,如名片、产品卡片
- 🎲 3D 立方体:确保只看到面向观察者的面
- 📖 翻书效果:模拟真实的翻页动画
- 🎪 3D 轮播:旋转展示多个面板
- 🎮 游戏界面:3D 物体的正确渲染
重要注意事项
必须配合 3D 变换:backface-visibility 只在 3D 变换(如 rotateY, rotateX)中有意义,2D 旋转(rotate)不会产生背面
- 性能优化:设置为 hidden 可以让浏览器跳过背面的渲染,提升性能
- 浏览器兼容:现代浏览器都支持,旧版本可能需要 -webkit- 前缀
- 调试技巧:如果翻转效果不正常,检查是否忘记设置 backface-visibility: hidden
- 两面都要设置:卡片翻转时,正面和背面都应该设置 backface-visibility: hidden
Transform 的工作机制:父元素 vs 子元素
🤔 常见疑问
既然翻转后正面和背面都旋转了 180°,为什么不能直接对正面和背面分别执行
transform: rotateY(180deg)?
对比演示
✅ 方式 1:在父元素上旋转
/* 在爷容器上 hover,旋转父容器 */
.card-container:hover .card {
transform: rotateY(180deg);
}
原理:父元素旋转 180°,带着两个子元素一起在 3D 空间中旋转
❌ 方式 2:分别旋转子元素
.card-container:hover .front {
transform: rotateY(180deg);
}
.card-container:hover .back {
transform: rotateY(180deg);
}
/* 分别旋转子元素 */
原因:背面从 180° 变成 180°,没有变化!
为什么方式 2 不行?
🔑 关键原因:transform 属性会被覆盖
初始状态
.front { transform: rotateY(0deg); }
.back { transform: rotateY(180deg); }
悬停后(方式 2)
.card-container:hover .front {
transform: rotateY(180deg); ← 从 0° 变成 180° ✓
}
.card-container:hover .back {
transform: rotateY(180deg); ← 从 180° 变成 180° ✗ 没变化!
}
问题所在:CSS 的 transform 属性会被完全覆盖,而不是累加。
背面的初始值 rotateY(180deg) 被新值 rotateY(180deg) 覆盖,
但因为值相同,所以背面没有任何变化,依然停在 180° 的位置。
正确理解:3D 空间的旋转
✅ 方式 1:旋转整个 3D 空间
初始状态:
.card (0°)
├── .front: rotateY(0°) 相对于 .card → 绝对位置 0°
└── .back: rotateY(180°) 相对于 .card → 绝对位置 180°
悬停后:
.card (180°) ← 整个坐标系旋转了
├── .front: rotateY(0°) 相对于 .card → 绝对位置 0° + 180° = 180°
└── .back: rotateY(180°) 相对于 .card → 绝对位置 180° + 180° = 360° = 0°
关键:子元素的 transform 是相对于父元素的坐标系。 当父元素旋转时,子元素的相对角度不变,但绝对角度会改变。
❌ 方式 2:分别旋转元素
初始状态:
.front: rotateY(0°) → 绝对位置 0°
.back: rotateY(180°) → 绝对位置 180°
悬停后:
.front: rotateY(180°) → 绝对位置 180° ✓ 正面翻转成功
.back: rotateY(180°) → 绝对位置 180° ✗ 背面没有变化
问题:直接设置元素的 transform 会覆盖原有值。 背面需要旋转到 360°(或 0°),但我们只能设置成 180°。
总结:卡片翻转必须在父元素上执行旋转, 这样才能同时改变正面和背面的绝对角度。分别旋转子元素会因为 transform 属性覆盖而失败。
为什么需要三层结构?深度解析
标准三层结构
<div class="爷容器"> ← perspective(观察点)
<div class="父容器"> ← transform-style + rotateY(翻转者)
<div class="正面"></div> ← backface-visibility(被翻转的面)
<div class="背面"></div> ← backface-visibility(被翻转的面)
</div>
</div>
每一层的职责
爷容器 设置 perspective(透视点)
.card-container {
perspective: 1000px;
}
- 作用:定义观察者的位置,创建 3D 空间
- 为什么在外层?perspective 必须设置在父元素上,才能对子元素的 3D 变换生效
- 类比:就像你站在舞台前看表演,这个属性决定你站在哪里看
- 如果不设置:翻转会是平面的,没有 3D 透视效果
父容器 设置 transform-style 和执行 rotateY
.card {
transform-style: preserve-3d;
transition: transform 0.6s;
}
.card-container:hover .card {
transform: rotateY(180deg);
}
- transform-style: preserve-3d - 让子元素保持在 3D 空间中(而不是被压平)
- transform: rotateY(180deg) - 执行翻转动作
- 为什么在这一层?需要同时翻转正面和背面,所以在它们的父元素上执行旋转
- 类比:这是舞台上的转盘,带着上面的演员一起旋转
- 如果不设置 preserve-3d:子元素会被压平成 2D,背面隐藏会失效
子元素 正面和背面
.card-front,
.card-back {
position: absolute;
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
- position: absolute - 让两个面重叠在同一位置
- backface-visibility: hidden - 背面朝向观察者时隐藏
- 背面预先翻转 180° - 这样当父容器翻转 180° 时,背面刚好正面朝向你
- 类比:两个演员背靠背站在转盘上,转盘旋转时自动切换
为什么不能少一层?
❌ 错误:只有两层
<div class="card">
<div class="front"></div>
<div class="back"></div>
</div>
.card {
perspective: 1000px;
transform: rotateY(180deg);
}
问题:perspective 和 transform 在同一个元素上,perspective 不会对自己的 transform 生效, 只会对子元素生效。结果就是没有透视效果。
✅ 正确:三层结构
<div class="container">
<div class="card">
<div class="front"></div>
<div class="back"></div>
</div>
</div>
.container {
perspective: 1000px;
}
.card {
transform: rotateY(180deg);
}
正确:perspective 在父元素,对子元素的 transform 生效,产生正确的 3D 透视效果。
完整的卡片翻转模板
/* ============ HTML 结构 ============ */
<div class="card-container"> <!-- 爷容器:观察点 -->
<div class="card"> <!-- 父容器:翻转者 -->
<div class="card-front">正面内容</div>
<div class="card-back">背面内容</div>
</div>
</div>
/* ============ CSS 样式 ============ */
/* 第 1 层:爷容器 - 设置观察点 */
.card-container {
perspective: 1000px; /* 必须在父元素上 */
}
/* 第 2 层:父容器 - 执行翻转 */
.card {
transform-style: preserve-3d; /* 保持 3D 空间 */
transition: transform 0.6s;
}
.card-container:hover .card {
transform: rotateY(180deg); /* 翻转整个卡片 */
}
/* 第 3 层:子元素 - 正面和背面 */
.card-front,
.card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden; /* 关键!隐藏背面 */
}
.card-back {
transform: rotateY(180deg); /* 背面预先翻转 */
}
记住这个模板:这是实现完美卡片翻转的标准写法,三层结构缺一不可!
深度理解:元素天生有正反面
🔑 核心概念
在 CSS 3D 变换中,每个 HTML 元素天生就有正面和背面,就像一张纸。这不是我们模拟出来的,而是 CSS 3D 的底层机制。
验证:单个元素的正反面
👆 注意右边的文字是镜像的!这就是同一个元素的背面。每个元素都有这两面。
三层结构的真正作用
- 不是创造正反面,而是组织和控制两个独立的元素
- front 元素:代表"卡片正面的内容",初始 rotateY(0deg)
- back 元素:代表"卡片背面的内容",预先 rotateY(180deg)
- card 父容器:作为"纸",翻转时带着两个子元素一起转
类比:想象一张真实的卡片,正面贴着一张贴纸(front 元素),背面也贴着一张贴纸(back
元素)。 当你翻转卡片时,两张贴纸跟着一起翻转。backface-visibility: hidden
让贴纸在背面朝向你时变透明。
工作流程图解
back 元素:180° + 180° = 360° = 0°(正面朝向你,显示)
💡 关键理解
front 和 back 都是独立的元素,都有自己的正反面。
通过让它们初始角度相差 180°,并设置 backface-visibility: hidden,
当父容器翻转时,它们会自动切换显示,产生完美的卡片翻转效果。