CSS 3D 探秘:从布局基础到 3D 立方体
通过几个简单的 HTML/CSS 示例,一步步理解现代 CSS 布局与 3D 变换的核心概念。
一、起点:块级与行内——HTML 元素的两大家族
一切 CSS 布局的根基,都建立在浏览器对 HTML 元素的两大分类之上:
| 类型 | 代表元素 | 特点 |
|---|---|---|
| 块级(block) | div、p、ul | 可以设置宽高;独占一行,会把兄弟元素"挤"到下一行 |
| 行内(inline) | span、a | 不能设置宽高;不会换行,和兄弟元素和平共处 |
/* 块级元素天然独占一行 */
div { display: block; }
/* 行内元素随文字流排列 */
span { display: inline; }
打破规则:inline-block
2.html 演示了一个巧妙的中间态——行内块级:
.box {
background-color: red;
display: inline-block;
width: 50%;
}
两个 div 并排显示,各自占据 50% 宽度——既不会把兄弟挤下去(行内特性),又能设置宽高(块级特性)。
⚠️ inline-block 的"天坑" :HTML 中标签之间的换行符
\n会被渲染为一个空格字符。两个inline-block元素之间因此会有一个微小的间隙。这是新手最容易踩的坑之一。
二、格式化上下文:布局的"游戏规则"
display 属性不仅仅是改变元素的外在表现,更重要的是它开启了不同的格式化上下文(Formatting Context) ——可以理解为布局的游戏规则:
浏览器默认 → display 手动切换 → 格式化上下文(flex / inline-block / grid)
Flex 弹性布局
3.html 展示了 flex 的核心用法:
.box {
display: flex; /* 开启弹性格式化上下文 */
/* flex-direction: row; /* 默认:主轴水平 */
}
.item {
flex: 1; /* 每个子元素等分剩余空间 */
background-color: red;
text-align: center;
}
关键认知:display: flex 是设置在父容器上的——父与子之间的布局关系由父容器说了算。四个 .item 自动等宽排列,无需手动计算百分比。
三、水平垂直居中:移动端适配的基石
common.css 中展示了最经典、最实用的居中方案:
html, body {
height: 100vh; /* vh = viewport-height,视窗高度 */
display: flex;
flex-direction: row; /* 默认值,主轴水平 */
justify-content: center; /* 主轴(水平)居中 */
align-items: center; /* 次轴(垂直)居中 */
}
移动端新单位
vh(viewport-height):视窗高度的 1%,100vh= 满屏高度vw(viewport-width):视窗宽度的 1%- 相比
100%,100vh直接相对于视窗,不依赖父元素高度
这构成了移动端适配的黄金组合:flex + vh/vw + justify-content/align-items。
四、CSS 3D:让平面"立起来"
1.html + common.css 的核心——一个纯 CSS 实现的 3D 旋转立方体。
4.1 三维世界的入口:perspective
.box-wrap {
width: 200px;
height: 200px;
perspective: 600px; /* 3D 核心:视距 */
}
perspective 定义了观察者与 z=0 平面的距离。值越小,透视效果越强烈(物体显得越大、越近);值越大,透视越平缓。可以理解为"相机镜头"的焦距。
4.2 保留 3D 空间:transform-style
.box {
position: relative;
transform-style: preserve-3d; /* 关键:让子元素保留 3D 位置 */
animation: rotate 5s linear infinite;
}
不加 preserve-3d,所有子元素会被"拍扁"到父元素的 2D 平面——3D 效果荡然无存。
4.3 搭建立方体的六个面
一个立方体有 6 个面,每个面都是 200×200 的正方形,通过 position: absolute 叠加在同一位置,然后用 transform 将它们"推"到空间的对应位置:
.face {
width: 200px;
height: 200px;
position: absolute; /* 所有面叠在一起 */
opacity: 0.8;
}
/* 前面:沿 Z 轴向外推 100px(半边长) */
.front { transform: translateZ(100px); }
/* 后面:沿 Z 轴向内推 100px,再翻转 180° 让文字正向 */
.back { transform: translateZ(-100px) rotateY(180deg); }
/* 左面:沿 X 轴左移 100px,绕 Y 轴旋转 -90° */
.left { transform: translateX(-100px) rotateY(-90deg); }
/* 右面:沿 X 轴右移 100px,绕 Y 轴旋转 90° */
.right { transform: translateX(100px) rotateY(90deg); }
/* 上面:沿 Y 轴上移 100px,绕 X 轴旋转 90° */
.top { transform: translateY(-100px) rotateX(90deg); }
/* 下面:沿 Y 轴下移 100px,绕 X 轴旋转 -90° */
.bottom { transform: translateY(100px) rotateX(-90deg); }
4.4 让立方体转起来:@keyframes
@keyframes rotate {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(360deg); }
}
完整的动画链条:
animation: rotate 5s linear infinite
↓ ↓ ↓ ↓
动画名 时长 缓动 循环
4.5 立方体构建原理图
┌──────────┐
│ top │ translateY(-100px) rotateX(90deg)
└──────────┘
┌──────────┬──────────┬──────────┐
│ left │ front │ right │
│ -100px X │ +100px Z │ +100px X │
│ -90° Y │ │ +90° Y │
└──────────┴──────────┴──────────┘
┌──────────┐
│ bottom │ translateY(100px) rotateX(-90deg)
└──────────┘
┌──────────┐
│ back │ translateZ(-100px) rotateY(180deg)
└──────────┘
4.6 GPU 加速:隐藏的福利
CSS 3D 不仅用于 3D 效果。transform: translateZ(0) 或 will-change: transform 会触发 GPU 加速——即使是 2D 界面,有时也会刻意"3D 化"来利用 GPU 渲染,提升动画流畅度。这比传统的 left/top 动画性能好得多,因为 transform 不走重排(reflow),只在合成层上操作。
五、知识全景图
HTML 元素
├── 块级 (block) ── 独占一行,可设宽高
├── 行内 (inline) ── 不换行,不可设宽高
└── 行内块级 (inline-block) ── 不换行 + 可设宽高 ⚠️ 空格坑
格式化上下文
├── display: flex ── 弹性布局,一维排列
├── display: grid ── 网格布局,二维排列
└── display: inline-block ── 行内块级上下文
定位
├── position: relative ── 相对自身原始位置偏移
└── position: absolute ── 相对最近的定位祖先偏移
CSS 3D
├── perspective ── 视距,3D 世界的入口
├── transform-style: preserve-3d ── 保留子元素的 3D 空间
├── transform: translateZ/rotateY/rotateX ── 空间位移与旋转
└── @keyframes + animation ── 让 3D 世界动起来
六、动手试试
想亲手体验?只需三个文件:
- 新建
1.html,引入common.css - 复制六个面的 HTML 结构到页面
- 在浏览器中打开,看着一个半透明的彩色立方体在你面前缓缓旋转
你可以尝试调整这些参数来感受变化:
- 把
perspective: 600px改成200px——透视变强烈 - 把
animation的5s改成1s——旋转加速 - 给
.box加上transform: rotateX(20deg)——换个观察角度
CSS 3D 的世界,比你想象的更简单,也更有趣 🎲