🧊 从零到一:CSS 3D 旋转立方体完全指南
🌟 这是一篇带你亲手搭建 3D 旋转立方体 的硬核笔记------从 元素类型 聊到 flex 布局 ,从 定位 深入 3D 变换 ,最后用 动画 让立方体转起来。全文逻辑闭环、图文并茂,读完你不仅能复刻经典案例,更能掌握一套举一反三的 CSS 3D 心法。建议收藏慢慢啃,边看边动手~ 🧩
📦 写在前面
3D 效果在前端世界里总是自带「哇塞」滤镜。无论是产品展示、炫酷首页,还是个人博客的交互彩蛋,CSS 3D 都能用最轻量的方式带来视觉冲击。
但很多同学初学 3D 时,总会被 transform、perspective、preserve-3d 这些属性绕晕。别急,今天我们就通过一个 经典 3D 旋转立方体 项目,把 CSS 3D 的底层逻辑全部捋一遍。
本文会沿着这条链路展开:
元素类型 → flex 弹性布局 → 定位 → 3D 属性 → 动画
每块知识点都配有直观的比喻和代码示例。你跟着走一遍,不仅能跑通立方体,更能理解「为什么这样写」,以后遇到任何 3D 场景都能从容应对。🚀
🎨 项目效果预览
我们先来看看最终成品长什么样:
- 一个 六面彩色立方体,每个面标有「前/后/左/右/上/下」字样
- 整体在页面 正中央 ,持续绕 Y 轴 匀速旋转
- 所有面 半透明,可以看到背面的结构,立体感拉满
1️⃣ 3D & canvas 开篇小叙
3D 在前端世界里有两种主流实现方式:
- canvas:HTML5 新增标签,通过 JavaScript API 控制绘图,适合复杂 3D 场景(如 Three.js)
- CSS 3D:用 CSS 属性触发 3D 绘制,轻量、简洁,适合 UI 层面的立体效果
用 CSS 写 3D,不仅是为了做 3D 本身,它还会带来一个隐藏福利------GPU 加速 。哪怕你只是在做 2D 界面,有时候也会手动"3D 化"一些元素(比如加个 translateZ(0)),利用 GPU 提升渲染性能,让动画更丝滑。⚡
本文通过一个 3D 旋转立方体 项目,一步步讲解用到的 CSS 核心知识:元素类型 → flex 弹性布局 → 定位 → 3D 属性 → 动画。读完你不仅能理解这段代码,还能举一反三搭建自己的 3D 效果。
2️⃣ 元素类型与 display
HTML 元素按显示方式主要分两类:
-
块级元素 (如
div、ul、p)默认
display: block→ 独占一行,可以设置宽高 -
行内元素 (如
span、a、strong)默认
display: inline→ 不换行,不能 设置宽高
我们可以用 display 属性手动切换元素的显示模式:
| 值 | 特点 |
|---|---|
block |
独占一行,可设宽高 |
inline |
不换行,不可设宽高 |
inline-block |
不换行,且可设宽高 |
none |
隐藏,不占位置 |
flex |
弹性容器,一维自动布局 |
grid |
网格容器,二维布局 |
⚠️ inline-block 的换行空格坑
inline-block 之间如果 HTML 代码换行,浏览器会把它渲染成 一个空格 。比如两个 50% 宽的 inline-block 换行写,就会变成 50% + 空格 + 50% > 100%,导致第二个元素被挤到下一行。
- 解决①:把两个标签贴在一起 写:
<div></div><div></div> - 解决②(推荐):父元素改用 flex 布局(详见下一章)
📖 基础概念速查
选择器:
*通配符(选中所有元素).类名选中指定类标签名选中指定标签a, b分组(逗号表示同时生效)a b后代(空格表示嵌套关系)单位:
px像素%相对父元素vh/vw视窗百分比s/ms动画时间deg角度常见属性:
属性 作用 示例 width/height宽高 width: 200px;background背景色 background: red;font-size字号 font-size: 30px;color文字颜色 color: #fff;opacity透明度 0~1 opacity: 0.5;💡
opacity会让整个元素(含子元素和文字)一起变透明。和它类似的还有rgba(红,绿,蓝,透明度),区别是rgba只影响当前颜色属性 ,子元素不受影响。本项目用opacity: 0.5让六个面整体半透明,从而能透过前面看到后面的面,立体感更强。
3️⃣ 弹性布局(flex)
掌握了元素类型,接下来看最重要的布局方式------flex。给父元素加 display: flex,就开启了一个弹性格式上下文,子元素自动按规则排列。
🧭 主轴与交叉轴
默认 flex-direction: row(横排):
css
交叉轴 ↓
┌──┐ ┌──┐ ┌──┐
│A │ │B │ │C │ ← 主轴 →
└──┘ └──┘ └──┘
flex-direction: column(竖排)时两轴对调:
css
主轴 ↓
┌──┐
│A │
├──┤
│B │ ← 交叉轴 →
├──┤
│C │
└──┘
🧠 口诀 :
justify-content永远管主轴 ,align-items永远管交叉轴。
🔧 核心属性
容器属性 (写在有 display:flex 的元素上):
| 属性 | 作用 | 常用值 |
|---|---|---|
justify-content |
主轴排列 | flex-start / center / flex-end / space-between / space-around |
align-items |
交叉轴对齐 | stretch(默认) / flex-start / center / flex-end |
flex-direction |
主轴方向 | row(横排) / column(竖排) |
flex-wrap |
是否换行 | nowrap / wrap |
justify-content 效果图解:
flex-start→ 靠左(或靠上)center→ 居中space-between→ 两端贴边,中间均分space-around→ 每个元素周围均分间距
项目属性(写在子元素上):
| 属性 | 作用 |
|---|---|
flex: N |
按比例 N 分配剩余空间 |
align-self |
单独控制交叉轴位置 |
order |
改变排序 |
margin-left: auto |
推到最右 |
🍰 flex: N 分蛋糕
flex: 1 → 所有子元素平分(1:1:1)
flex: 2 → 占 2 份,是别人的 2 倍宽
数字就是权重 ,越大分得越多。flex: 0 则保持原大小,不参与分配。
📦 margin: 0 auto
margin: 0 auto = 上下 0,左右自动(剩余空间左右平分 → 居中)。
在 flex 时代,用 justify-content: center 更简洁,margin: 0 auto 属于老式居中方法,但在某些场景依然好用。
🧩 本项目中的两层 flex 居中
1️⃣
body的display:flex + justify-content:center + align-items:center→ 整个立方体在屏幕正中间2️⃣
.face的display:flex + justify-content:center + align-items:center→ 每个面上「前/后/左/右/上/下」文字在方块内居中原理 :flex 只管道接子元素。
body的子元素是.box-wrap,所以管立方体位置;.face的子元素是文字,所以管文字居中。两个 flex 各管各的,互不干扰。另外注意,六个面看起来像"居中"在页面里,其实是它们尺寸和
.box完全一样大(200×200),把父容器铺满了 。真正居中靠的是body的 flex,而不是面自己。
4️⃣ 定位(position)
flex 解决了排列问题,但六个面要精确叠放在同一个位置,还需要定位。接下来看看 position 怎么用。
📌 五种定位一览
| 值 | 比喻 | 一句话 |
|---|---|---|
static(默认) |
老实人 | 规规矩矩排文档流 |
relative |
站桩的人 | 站原地不动,给 absolute 子元素当"参照桩" |
absolute |
离家出走 | 脱离文档流,找最近有定位的祖先挂号 |
fixed |
钉窗户上 | 相对浏览器窗口定位,滚动也不动 |
sticky |
粘人的 | 平时正常排,滚到位置就粘住 |
🧱 relative --- 核心是当"参照物"
自己不移动,但为 absolute 子元素提供定位参照:
html
<!-- ❌ 没有 relative:子元素飘到页面左上角 -->
<div>
<div style="position: absolute; top:0; left:0;">飘了</div>
</div>
<!-- ✅ 有 relative:子元素有家了 -->
<div style="position: relative;">
<div style="position: absolute; top:0; left:0;">贴在爸爸左上角</div>
</div>
如果给 relative 自身设置了 top/left,它是相对于自己原来的位置 偏移,且原来的坑还留着,后面元素不会顶上来。
✈️ absolute --- 三条铁律
- 脱离文档流:飞走,不占位置,后面元素会顶上来
- 查找规则 :往上找最近有定位(
position ≠ static)的祖先作为参照 - 找不到参照 :相对于整个页面(
html)定位
html
<div style="position: relative;"> ← 第1层,有定位 ✓
<div> ← 第2层,没定位,跳过
<div style="position: absolute;">← 第3层 → 找到第1层
</div>
</div>
</div>
配合 top/left/right/bottom 精确摆放。任意 HTML 标签都能用 absolute。
absolute 在本项目中的三个作用:
- 统一原点 :6 个
.face全部从.box的 (0,0) 同一位置出发,translate才能算对。如果不用 absolute,6 个块级 div 会从上到下一列排开,translate起点各不相同,拼不出立方体。- 叠加覆盖:面全部摞在一起,后面 translate 推开才有 3D 立体感。
- 脱离文档流 :absolute 让面"飞走"不占位,
.box不会被 6 个 200×200 的面撑得变形。
🤝 relative + absolute 黄金搭档
css
.card { position: relative; } /* 爸爸站桩 */
.card .badge {
position: absolute;
top: 10px; right: 10px; /* 孩子贴在右上角 */
}
⚖️ relative vs absolute
| relative | absolute | |
|---|---|---|
| 脱离文档流? | 否 | 是 |
| 参照谁? | 自己原来的位置 | 最近有定位的祖先 |
| 用途 | 给子元素当锚点 | 精确摆放、叠加层 |
🆚 flex vs 绝对定位
| flex | 绝对定位 | |
|---|---|---|
| 理念 | 规则驱动,自动归位 | 坐标驱动,手动摆放 |
| 子元素位置 | 排列规则决定 | top/left 精确控制 |
| 适用场景 | 列表排列、等分、自适应 | 叠加层、徽标、3D 拼合 |
5️⃣ 3D 核心属性
现在 flex 负责居中、absolute 负责叠面------但要让这些面在三维空间里"立起来",还需要几个 CSS 3D 专属属性。
👁️ perspective(透视 / 视距)
写在外层盒子 (.box-wrap)上。
就像你离物体有多远看它:视距越大,看到的效果越小;视距越小,透视感越强。必须要有透视才能看到 3D 效果。
css
.box-wrap {
perspective: 800px; /* 模拟 800px 外的视角 */
}
🧊 transform-style: preserve-3d
写在内层盒子 (.box)上。
告诉浏览器:"我和子元素用 3D 空间渲染,不要拍扁成平面"。没有它,6 个面叠在一起永远看不出立体。
css
.box {
transform-style: preserve-3d;
}
🔄 transform 变换函数
| 函数 | 含义 | 方向 |
|---|---|---|
translateX(N) |
沿 X 轴移动 | 正值→右,负值→左 |
translateY(N) |
沿 Y 轴移动 | 正值→下,负值→上(屏幕坐标) |
translateZ(N) |
沿 Z 轴移动 | 正值→靠近你,负值→远离你 |
rotateX(deg) |
绕 X 轴旋转 | 正值顺时针(从正X看) |
rotateY(deg) |
绕 Y 轴旋转 | 正值顺时针(从正Y看) |
rotateZ(deg) |
绕 Z 轴旋转 | 正值顺时针(从正Z看) |
⚠️ 书写顺序非常重要 :
translateX(100px) rotateY(90deg)是先平移再旋转。如果反过来(先旋转再平移),坐标系转了方向,最终位置完全不同。做立方体必须先 translate 推开面,再 rotate 转弯面朝外。
6️⃣ 3D 立方体实战
理论知识准备完毕,接下来看这些属性在本项目中是怎么组合使用的。
🖥️ 页面视窗初始化
css
html, body {
height: 100vh; /* 用视窗高度占满全屏,比 100% 更稳定 */
margin: 0;
overflow: hidden;
}
100vh(视窗高度)让页面占满全屏,比100%更稳定(不依赖父元素)。- 配合
body上的display: flex + justify-content: center + align-items: center,.box-wrap作为body的子元素被居中在页面正中间。 - 💡 小知识:
<html>没背景时,<body>的背景会被浏览器"借走"铺满全屏,这是浏览器的默认行为。
🏗️ 整体结构
scss
HTML 嵌套结构: CSS 定位关系:
.box-wrap static(默认)
└── .box relative ← 站桩,给6个面做参照!
├── .face(front) absolute ← 全叠在 .box 左上角
├── .face(back) absolute
├── .face(left) absolute
├── .face(right) absolute
├── .face(top) absolute
└── .face(bottom) absolute
- 外层
.box-wrap负责布局:设置宽高、透视距离(perspective) - 内层
.box负责展示:开启 3D 空间(transform-style)和动画 - 6 个
.face全部absolute叠在.box的 (0,0),再用translate在 3D 空间推开
📐 六个面的立体结构
scss
┌──────────┐
│ 上(top) │
│ │
┌───────┼──────────┼───────┐
│左(left)│前(front)│右(right)│
└───────┼──────────┼───────┘
│ 下(bottom)│
└──────────┘
背面(back)在后面
- 用途:3D 立方体演示、骰子、轮播图、相册、360度产品展示
- 原理 :6 张纸板,通过
translate推到不同方向,再用rotate转弯面朝外,拼成立方体
六个面不是"居中"在
.box里,而是尺寸和.box完全一样大(200×200),铺满了父容器 。然后各自用translate从叠在一起的位置推开,在 3D 空间拼出立方体。
🎨 六个面的颜色与 transform
| 面 | 颜色 | transform |
|---|---|---|
| 前 front | 蓝 #4299e1 | translateZ(100px) |
| 后 back | 红 #f5656f | translateZ(-100px) rotateY(180deg) |
| 左 left | 绿 #48bb78 | translateX(-100px) rotateY(-90deg) |
| 右 right | 橙 #ed8936 | translateX(100px) rotateY(90deg) |
| 上 top | 紫 #9f7aea | translateY(-100px) rotateX(90deg) |
| 下 bottom | 黄 #ecc94b | translateY(100px) rotateX(-90deg) |
7️⃣ CSS 动画(animation)
最后让整个 .box 绕 Y 轴匀速旋转,立方体就"活"起来了------
简写语法 :animation: 动画名称 时长 速度曲线 循环次数;
css
animation: rotate 5s linear infinite;
| 参数 | 含义 | 常用值 |
|---|---|---|
rotate |
动画名称(自定义,对应 @keyframes) | --- |
5s |
一次动画的时长 | 1s / 2s / 500ms |
linear |
速度曲线 | linear(匀速) / ease / ease-in-out |
infinite |
循环次数 | 1 / 3 / infinite(无限) |
@keyframes 用百分比定义动画各阶段,浏览器自动计算中间过渡。0% 等于 from,100% 等于 to:
css
@keyframes rotate {
0% { transform: rotateY(0deg); } /* 开始:0度 */
100% { transform: rotateY(360deg); } /* 结束:转一圈 */
}
🔗 技术链路回顾
一条线串起所有知识点:
scss
100vh 铺满全屏
↓
body 的 flex 居中 .box-wrap
↓
.box-wrap 设 perspective(透视)
↓
.box 开 relative 站桩 + preserve-3d 开 3D 空间
↓
6 个 face absolute 叠在同一原点
↓
translate 推开面 + rotate 转弯面
↓
@keyframes rotateY 让整个 .box 旋转
↓
🎉 一个完整的 CSS 3D 立方体诞生!
💡 拓展思考
到这里,你已经掌握了 CSS 3D 的核心套路。你可以试着:
- 把立方体改成 长方体(宽高不同,translate 值相应调整)
- 给每个面加上 图片背景,做成 3D 相册
- 用
rotateX+rotateY组合,实现 任意角度的 3D 卡片翻转 - 结合 JS 交互,用鼠标拖拽控制立方体旋转方向
CSS 3D 的乐趣就在于「组合」------几个简单的变换函数拼在一起,就能创造出无限可能。动手试试吧!💪
📚 参考与延伸
如果这篇文章对你有帮助,欢迎点赞 👍、收藏 ⭐、评论 💬 三连支持~
有任何疑问,也欢迎在评论区留言,我会尽量回复。
Happy Coding! 🧑💻✨
