CSS 3D 属性为页面带来了全新的视觉维度,让原本平面的元素能够在三维空间中展示和运动,极大地提升了用户体验和页面表现力。本文将从 CSS 3D 的核心概念和属性讲起,逐步深入,最后通过两个实用的案例动画,帮助你全面掌握 CSS 3D 技术的应用。
一、先搞懂 CSS 3D 的 3 个核心概念
在写代码前,必须先建立 “3D 空间” 的认知 ——CSS 3D 本质是在浏览器中模拟三维坐标系,所有元素都在这个坐标系中定位和变换。这三个概念是一切效果的基础:
1. 3D 坐标系:x/y/z 轴分别代表什么?
CSS 3D 采用 “右手坐标系”,记住这三个轴的方向,就能理解元素的移动和旋转逻辑:
- x 轴:水平方向(左右),正方向向右,负方向向左;
- y 轴:垂直方向(上下),正方向向下,负方向向上;
- z 轴:纵深方向(前后),正方向指向屏幕外(靠近你),负方向指向屏幕内(远离你)。
2. perspective:给眼睛一个 “距离”,让 3D 有立体感
没有 perspective
的 3D 都是 “假 3D”—— 它模拟人眼到 “3D 舞台” 的距离,值越小,立体感越强(就像凑近看物体),值越大,立体感越弱(像远处看)。
注意:perspective
要加在父容器上,作用是给子元素创建 “3D 观察空间”,而不是直接加在子元素上。
3. transform-style: preserve-3d:让子元素 “继承” 3D 空间
默认情况下,CSS 会把 3D 变换后的子元素 “压平” 到父元素的平面上(transform-style: flat
),这会导致子元素之间的 3D 层级消失。只有给父容器设置 transform-style: preserve-3d
,才能让子元素在真正的 3D 空间中排列。
二、从基础到进阶:3 个实战案例
理论说完,直接上代码 —— 每个案例都包含完整 HTML/CSS,复制到文件就能运行,关键代码已标注注释。
案例 1:3D 旋转立方体(基础入门)
最经典的 3D 案例,用 6 个 div 组成立方体的 6 个面,通过 transform
定位到 3D 空间,再添加旋转动画。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D立方体旋转效果</title>
<style>
.cube-stage {
width: 400px;
height: 400px;
margin: 80px auto;
perspective: 1500px;
/* 透视效果,增强立体感 */
}
.cube {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
/* 开启3D空间 */
animation: rotateCube 10s linear infinite;
/* 自动旋转动画 */
}
/* 立方体的6个面 */
.cube-face {
width: 200px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -100px;
opacity: 0.8;
border: 2px solid white;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
color: white;
font-weight: bold;
}
/* 前面:沿Z轴正向平移100px(立方体边长的一半) */
.front {
background-color: #4285f4;
transform: translateZ(100px);
}
/* 后面:沿Z轴负向平移100px,再绕Y轴旋转180度 */
.back {
background-color: #ea4335;
transform: translateZ(-100px) rotateY(180deg);
}
/* 左面:沿X轴负向平移100px,再绕Y轴旋转-90度 */
.left {
background-color: #fbbc05;
transform: translateX(-100px) rotateY(-90deg);
}
/* 右面:沿X轴正向平移100px,再绕Y轴旋转90度 */
.right {
background-color: #34a853;
transform: translateX(100px) rotateY(90deg);
}
/* 上面:沿Y轴负向平移100px,再绕X轴旋转90度 */
.top {
background-color: #9c27b0;
transform: translateY(-100px) rotateX(90deg);
}
/* 下面:沿Y轴正向平移100px,再绕X轴旋转-90度 */
.bottom {
background-color: #00acc1;
transform: translateY(100px) rotateX(-90deg);
}
/* 立方体旋转动画:绕X轴和Y轴同时旋转 */
@keyframes rotateCube {
0% {
transform: rotateX(0deg) rotateY(0deg);
}
100% {
transform: rotateX(360deg) rotateY(360deg);
}
}
</style>
</head>
<body>
<div class="cube-stage">
<div class="cube">
<div class="cube-face front">前</div>
<div class="cube-face back">后</div>
<div class="cube-face left">左</div>
<div class="cube-face right">右</div>
<div class="cube-face top">上</div>
<div class="cube-face bottom">下</div>
</div>
</div>
</body>
</html>
关键思路:
立方体的边长是 300px,所以每个面需要向对应方向移动 “边长的一半”(150px),才能刚好组成立方体;旋转动画同时绕 x 轴和 y 轴,让立方体的 6 个面都能展示出来。
案例 2:3D 翻牌效果(交互进阶)
在实际项目中,3D 翻牌常用于卡片详情、答题对错判断等场景。这个案例实现 “鼠标悬停时,卡片从正面翻到背面” 的效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CSS 3D 翻牌效果</title>
<style>
/* 1. 卡片容器:设置 3D 空间和尺寸 */
.card-container {
width: 400px;
height: 600px;
margin: 50px auto;
perspective: 1200px;
/* 稍大的距离,让翻牌更自然 */
cursor: pointer;
}
/* 2. 卡片主体:承载正反面,设置 3D 保留和过渡 */
.card {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
/* 关键:添加过渡,让翻牌有动画感 */
transition: transform 0.6s ease;
}
/* 3. 鼠标悬停时:卡片绕 y 轴旋转 180° */
.card-container:hover .card {
transform: rotateY(180deg);
}
/* 4. 卡片正反面:统一样式,隐藏背面(关键) */
.card-front,
.card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
/* 关键:隐藏被旋转到背面的元素(避免正面和背面重叠) */
border-radius: 16px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 30px;
box-sizing: border-box;
}
/* 5. 正面样式 */
.card-front {
background: linear-gradient(135deg, #ff6b6b, #feca57);
color: #fff;
}
/* 6. 背面样式:默认旋转 180°(初始状态背对用户) */
.card-back {
background: linear-gradient(135deg, #48dbfb, #1dd1a1);
color: #fff;
transform: rotateY(180deg);
/* 关键:初始状态背面朝上(但被 backface-visibility 隐藏) */
}
/* 辅助样式:图片和文字 */
.card-img {
width: 200px;
height: 200px;
border-radius: 50%;
margin-bottom: 30px;
object-fit: cover;
}
.card-title {
font-size: 32px;
margin-bottom: 16px;
}
.card-desc {
font-size: 18px;
text-align: center;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="card-container">
<div class="card">
<!-- 卡片正面 -->
<div class="card-front">
<img src="https://picsum.photos/200/200?random=1" alt="正面图片" class="card-img">
<h2 class="card-title">前端进阶笔记</h2>
<p class="card-desc">点击卡片,查看 CSS 3D 核心知识点</p>
</div>
<!-- 卡片背面 -->
<div class="card-back">
<h2 class="card-title">CSS 3D 核心属性</h2>
<p class="card-desc">1. perspective:创建 3D 观察距离<br>2. transform-style: preserve-3d:保留 3D 层级<br>3.
backface-visibility: hidden:隐藏背面元素<br>4. transform: rotateY(180deg):绕 y 轴旋转</p>
</div>
</div>
</div>
</body>
</html>
关键思路:
backface-visibility: hidden
是核心:它让元素的 “背面” 在旋转时不可见,避免正面和背面重叠显示;- 背面初始状态用
rotateY(180deg)
旋转,这样默认显示正面;鼠标悬停时,卡片整体旋转 180°,背面就会转到正面。
案例 3:3D 照片墙(综合实战)
用多个图片元素组成 “立体照片墙”,鼠标拖动时照片墙跟随旋转,模拟真实空间的交互感。这个案例需要结合一点 JavaScript 处理鼠标事件。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>CSS 3D 照片墙</title>
<style>
/* 1. 全局样式:消除默认边距,设置背景 */
body {
margin: 0;
padding: 50px;
background: #2c3e50;
min-height: 100vh;
box-sizing: border-box;
}
/* 2. 照片墙容器:3D 空间和居中 */
.photo-wall {
width: 800px;
height: 500px;
margin: 0 auto;
position: relative;
perspective: 1500px;
/* 更大的距离,让照片墙更有空间感 */
transform-style: preserve-3d;
}
/* 3. 照片样式:绝对定位,添加过渡 */
.photo {
position: absolute;
width: 300px;
height: 400px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* 初始居中 */
backface-visibility: hidden;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
transition: transform 0.3s ease;
/* 平滑过渡,跟随鼠标移动 */
overflow: hidden;
}
/* 4. 照片图片:填充容器 */
.photo img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
</style>
</head>
<body>
<div class="photo-wall" id="photoWall">
<!-- 这里会用 JS 动态生成 6 张照片 -->
</div>
<script>
// 1. 获取照片墙容器
const photoWall = document.getElementById('photoWall');
// 2. 照片数量和角度分布(6 张照片,均匀分布在 360° 圆周上)
const photoCount = 6;
const angleStep = 360 / photoCount; // 每张照片之间的角度差:60°
const radius = 300; // 照片墙的“半径”(照片到中心的距离)
// 3. 动态生成照片
for (let i = 0; i < photoCount; i++) {
const photo = document.createElement('div');
photo.className = 'photo';
// 给每张照片设置不同的旋转角度和位置(核心:利用 rotateY 和 translateZ)
const angle = i * angleStep; // 当前照片的旋转角度
photo.style.transform = `
translate(-50%, -50%)
rotateY(${angle}deg) /* 绕 y 轴旋转对应角度 */
translateZ(${radius}px) /* 向 z 轴正方向移动半径距离,形成圆形 */
`;
// 添加图片(使用随机图片服务)
const img = document.createElement('img');
img.src = `https://picsum.photos/300/400?random=${i + 2}`;
img.alt = `照片 ${i + 1}`;
photo.appendChild(img);
photoWall.appendChild(photo);
}
// 4. 鼠标拖动控制旋转(交互核心)
let isDragging = false;
let startX = 0;
let currentRotateY = 0; // 当前照片墙的旋转角度
// 鼠标按下:记录初始位置
photoWall.addEventListener('mousedown', (e) => {
isDragging = true;
startX = e.clientX;
});
// 鼠标移动:计算旋转角度
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const moveX = e.clientX - startX;
// 控制旋转速度(移动 1px 对应旋转 0.5°,可调整)
currentRotateY += moveX * 0.5;
startX = e.clientX;
// 应用旋转到照片墙
photoWall.style.transform = `rotateY(${currentRotateY}deg)`;
});
// 鼠标松开:结束拖动
document.addEventListener('mouseup', () => {
isDragging = false;
});
// 鼠标离开窗口:结束拖动(避免异常)
document.addEventListener('mouseleave', () => {
isDragging = false;
});
</script>
</body>
</html>
关键思路:
- 照片排列:6 张照片按
60°
间隔绕 y 轴旋转,再用translateZ
向外移动相同距离,形成一个 “圆柱形” 的照片墙; - 鼠标交互:通过监听
mousedown/mousemove/mouseup
事件,计算鼠标水平移动距离,转化为照片墙的旋转角度,实现 “拖动旋转” 的交互。
三、CSS 3D 开发的 3 个避坑指南
- 不要忘记
transform-style: preserve-3d
:如果子元素的 3D 效果不显示,先检查父容器是否加了这个属性(很多新手会漏掉); perspective
的作用对象是父容器:直接给子元素加perspective
无效,必须加在父容器上,让子元素在父