从零到一:CSS 3D 旋转立方体完全指南

🧊 从零到一:CSS 3D 旋转立方体完全指南

🌟 这是一篇带你亲手搭建 3D 旋转立方体 的硬核笔记------从 元素类型 聊到 flex 布局 ,从 定位 深入 3D 变换 ,最后用 动画 让立方体转起来。全文逻辑闭环、图文并茂,读完你不仅能复刻经典案例,更能掌握一套举一反三的 CSS 3D 心法。建议收藏慢慢啃,边看边动手~ 🧩


📦 写在前面

3D 效果在前端世界里总是自带「哇塞」滤镜。无论是产品展示、炫酷首页,还是个人博客的交互彩蛋,CSS 3D 都能用最轻量的方式带来视觉冲击。

但很多同学初学 3D 时,总会被 transformperspectivepreserve-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 元素按显示方式主要分两类:

  • 块级元素 (如 divulp

    默认 display: block → 独占一行,可以设置宽高

  • 行内元素 (如 spanastrong

    默认 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️⃣ bodydisplay:flex + justify-content:center + align-items:center → 整个立方体在屏幕正中间

2️⃣ .facedisplay: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 --- 三条铁律

  1. 脱离文档流:飞走,不占位置,后面元素会顶上来
  2. 查找规则 :往上找最近有定位(position ≠ static)的祖先作为参照
  3. 找不到参照 :相对于整个页面(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 在本项目中的三个作用

  1. 统一原点 :6 个 .face 全部从 .box 的 (0,0) 同一位置出发,translate 才能算对。如果不用 absolute,6 个块级 div 会从上到下一列排开,translate 起点各不相同,拼不出立方体。
  2. 叠加覆盖:面全部摞在一起,后面 translate 推开才有 3D 立体感。
  3. 脱离文档流 :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% 等于 from100% 等于 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! 🧑‍💻✨

相关推荐
疯狂的魔鬼1 小时前
多角色督办任务详情页:从权限矩阵到组件拆分的完整实现
前端·vue.js·架构
codexu_4612291871 小时前
NoteGen 里一条记录如何变成 Markdown
前端·笔记·rust·tauri
meilindehuzi_a1 小时前
从 Canvas 到 Vibe Coding:HTML5 游戏开发入门与 AI 飞机大战实战
前端·人工智能·html5
lichenyang4531 小时前
鸿蒙 Web 容器(一):怎么把一个 H5 页面嵌进鸿蒙页面?
前端
奇奇怪怪的2 小时前
浏览器线程与进程深度剖析
前端
渣波2 小时前
手把手教你写出优雅的 API 接口调用
前端·javascript
YHL2 小时前
🧊 CSS 3D 硬核解析:四个属性手写旋转立方体
前端·css·html
毛骗导演2 小时前
Tool Boundary:如何让大模型永远不知道也不会泄露用户敏感数据
前端·架构
零瓶水Herwt2 小时前
代替vue-currency-input使用原生货币符号
前端·vue.js