CSS3 布局系统
Flexbox + Grid——从"排列不了"到"想怎么排就怎么排"
用更少的代码,实现更灵活的页面布局为什么需要布局
没有布局系统时,网页像记事本——内容只能从上到下堆砌
传统堆砌
内容1
内容2
内容3
→ 无法水平排列
→ 无法垂直居中
→ 无法等高列
现代布局
[导航] [导航] [导航]
[ 侧栏 | 主内容 ]
[ 页脚 ]
→ 水平排列 ✓
→ 垂直居中 ✓
→ 等高列 ✓
| 问题 | 解决方案 |
|---|---|
| 元素水平排列 | Flexbox flex-direction: row |
| 元素垂直居中 | Flexbox align-items: center |
| 构建复杂网格 | Grid grid-template-areas |
| 响应式适配 | Grid minmax() + auto-fit |
传统布局痛点
在 Flexbox 和 Grid 出现之前,实现"垂直居中"需要多少代码?
传统居中(6 行)
.container {
position: relative;
}
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
需要绝对定位 + transform。translate 的百分比相对元素自身尺寸,所以不用量尺寸,但代码偏长。
Flexbox 居中(3 行)
.container {
display: flex;
justify-content: center;
align-items: center;
}
三行搞定。不需要知道元素尺寸,动态内容也没问题。
Part 1: Flexbox
一维布局模型——专注于在单个方向(行或列)上排列元素,特别擅长空间分配、对齐控制和顺序调整。
容器属性
flex-direction 定方向,justify-content 管主轴对齐,align-items 管交叉轴对齐,flex-wrap 控制换行。
项目属性
flex 控制空间分配比例,order 调整显示顺序 — 无需改 HTML 即可重排布局。
容器与项目
给父容器加 display: flex,它的直接子元素就变成了"弹性项目"
<div class="container">
<div class="item">项目1</div>
<div class="item">项目2</div>
<div class="item">项目3</div>
</div>
.container {
display: flex; /* 启用 Flexbox */
gap: 10px; /* 项目间距 */
}
.item {
padding: 20px;
background: #007bff;
color: white;
}
display: flex 的元素)—— 控制排列规则 ② 项目(直接子元素)—— 可以单独调整占比和顺序。
方向与主轴对齐
flex-direction 决定排列方向,justify-content 控制主轴上的对齐方式
flex-direction 方向
/* 水平排列(默认) */
flex-direction: row;
/* 水平反向 */
flex-direction: row-reverse;
/* 垂直排列 */
flex-direction: column;
/* 垂直反向 */
flex-direction: column-reverse;
justify-content 对齐
/* 左对齐(默认) */
justify-content: flex-start;
/* 居中 */
justify-content: center;
/* 两端对齐 */
justify-content: space-between;
/* 等间距 */
justify-content: space-around;
flex-direction 定方向(主轴),justify-content 管主轴对齐,align-items 管交叉轴对齐。
交叉轴与换行
垂直居中只需要 align-items: center 一行——这就是 Flexbox 流行的原因
align-items 交叉轴对齐
/* 拉伸填满(默认) */
align-items: stretch;
/* 顶部对齐 */
align-items: flex-start;
/* 垂直居中(最常用) */
align-items: center;
/* 文本基线对齐 */
align-items: baseline;
flex-wrap 换行控制
/* 不换行(默认,可能溢出) */
flex-wrap: nowrap;
/* 自动换行 */
flex-wrap: wrap;
/* 反向换行 */
flex-wrap: wrap-reverse;
配合 gap 使用,换行后间距自动一致。
项目属性详解
flex 控制空间分配,order 控制显示顺序
flex 空间分配
/* 等分空间 */
.item { flex: 1; }
/* 比例分配 1:2:3 */
.a { flex: 1; }
.b { flex: 2; }
.c { flex: 3; }
/* 固定宽度 + 弹性 */
.sidebar { flex: 0 0 200px; }
.main { flex: 1; }
order 显示顺序
/* 默认顺序 = DOM 顺序 */
.item { order: 0; }
/* 改变视觉顺序 */
.first { order: 1; }
.second { order: 2; }
.third { order: 3; }
DOM 顺序不变,视觉上按 order 值排列。适合响应式重排。
flex: 1 是 flex-grow: 1; flex-shrink: 1; flex-basis: 0% 的简写。大多数情况直接用 flex: 1 或 flex: 2 就够了。
Part 2: Grid
二维布局系统——可以同时控制行和列,适合构建页面整体结构和复杂网格。
网格基础
grid-template-columns/rows 定义行列,fr 单位按比例分配空间,gap 控制间距。
高级用法
grid-template-areas 画蓝图、跨行跨列布局、auto-fit + minmax 无需媒体查询的响应式网格。
网格基础结构
给容器加 display: grid,然后用行列定义画出网格
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* 三等分列 */
grid-template-rows: 100px 100px; /* 两行,各100px */
gap: 10px;
}
3 列 2 行网格与网格线编号
列线 1 列线 2 列线 3 列线 4
↓ ↓ ↓ ↓
┌─────────┬─────────┬─────────┐ ← 行线 1
│ 1 │ 2 │ 3 │
├─────────┼─────────┼─────────┤ ← 行线 2
│ 4 │ 5 │ 6 │
└─────────┴─────────┴─────────┘ ← 行线 3
引用某条网格线就能精确定位:grid-column: 1 / 3 表示从列线 1 跨到列线 3,也就是占第 1、2 两列。
1fr 1fr 1fr 表示把可用空间平均分成 3 份。就像切蛋糕——1fr 2fr 1fr 就是 1:2:1 的比例。
列宽定义方式
Grid 提供四种定义列宽的方式,从固定到灵活
| 方式 | 代码示例 | 适用场景 |
|---|---|---|
| 固定宽度 | 100px 200px 150px | 需要精确像素控制 |
| 比例分配 | 1fr 2fr 1fr | 按比例分空间(最常用) |
| minmax() | minmax(100px, 1fr) | 设最小/最大值 |
| repeat() | repeat(4, 1fr) | 重复相同模式 |
/* 四种写法对比 */
.fixed { grid-template-columns: 100px 200px 150px; }
.ratio { grid-template-columns: 1fr 2fr 1fr; }
.minmax { grid-template-columns: minmax(100px, 1fr) 200px minmax(150px, 2fr); }
.repeat { grid-template-columns: repeat(4, 1fr); }
命名区域布局
用 grid-template-areas 像画蓝图一样描述页面结构
.layout {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: 80px 1fr 60px;
gap: 10px;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
main { grid-area: main; }
footer { grid-area: footer; }
grid-template-areas 里的字符串,不用动 HTML。同一个名字可以跨多列/多行。
网格间距控制
gap 统一控制行列间距,告别 margin 的各种坑
传统 margin 方式
/* 首尾元素有多余空白 */
.items > * {
margin-right: 10px;
}
.items > *:last-child {
margin-right: 0; /* 手动清除 */
}
gap 属性
.container {
display: flex;
gap: 10px;
/* 就这一行,完事 */
}
/* 行列间距不同 */
.grid {
row-gap: 10px;
column-gap: 30px;
}
跨行列布局
用 grid-column 和 grid-row 让元素横跨多列/多行
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
}
/* 跨 3 列(整行) */
.feature {
grid-column: 1 / 4;
}
/* 跨 2 行 */
.sidebar {
grid-row: 2 / 4;
}
跨行跨列的最终效果
┌─────────────────────────────┐
│ 特色内容(跨 3 列) │ grid-column: 1 / 4
├──────────┬─────────┬─────────┤
│ │ 内容 1 │ 内容 2 │
│ 侧边栏 ├─────────┼─────────┤
│ (跨 2 行) │ 内容 3 │ 内容 4 │ grid-row: 2 / 4
└──────────┴─────────┴─────────┘
把起止网格线写成 grid-column: 1 / 4、grid-row: 2 / 4,元素就会自动横跨对应的行列,其余格子由普通项目填充。
响应式图片墙
一行代码实现无需媒体查询的响应式网格
.gallery {
display: grid;
/* 核心:自动适应屏幕宽度 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px;
}
| 关键词 | 作用 |
|---|---|
minmax(250px, 1fr) | 每列最小 250px,最大等分空间 |
auto-fit | 自动调整列数,填满可用空间 |
@media。
Part 3: 现代辅助
这些 CSS 特性本身不构成独立布局系统,但能让 Flexbox 和 Grid 更强大、更简洁。
间距与比例
gap 统一控制间距,minmax + auto-fit 实现无需媒体查询的响应式网格。
宽高比与对齐
aspect-ratio 保持宽高比,place-items/place-content 简化对齐代码。
gap 间距控制
告别 margin 的首尾空白问题
传统 margin
/* 每个项目加右边距 */
.item { margin-right: 10px; }
/* 再清除最后一个的 */
.item:last-child {
margin-right: 0;
}
首尾元素的间距需要特殊处理。
gap 属性
.container {
display: flex;
gap: 10px;
/* 就这一行,完事 */
}
自动处理间距,首尾无多余空白。
智能响应式网格
用 minmax() + auto-fit 替代一堆媒体查询
传统媒体查询
@media (max-width: 600px) {
.grid {
grid-template-columns: 1fr;
}
}
@media (min-width: 601px)
and (max-width: 900px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 901px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
一行代码
.grid {
display: grid;
grid-template-columns:
repeat(auto-fit,
minmax(250px, 1fr));
}
效果完全相同,代码量减少 80%。
宽高比控制
保持视频容器或卡片的宽高比,告别 padding 技巧
传统 padding 技巧
.video-container {
position: relative;
width: 100%;
}
.video-container::before {
content: "";
display: block;
padding-bottom: 56.25%;
/* 9/16 = 0.5625 */
}
.video-content {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
}
aspect-ratio
/* 视频容器 16:9 */
.video-container {
width: 100%;
aspect-ratio: 16 / 9;
}
/* 正方形卡片 */
.card {
aspect-ratio: 1 / 1;
}
一行代码搞定。宽度变,高度自动跟。
对齐快捷方式
place-items 和 place-content 是对齐属性的简写
分开写(4 行)
.container {
display: grid;
align-items: center;
justify-items: center;
align-content: center;
justify-content: center;
}
简写(2 行)
.container {
display: grid;
place-items: center;
/* = align-items + justify-items */
place-content: center;
/* = align-content + justify-content */
}
place-items: [align] [justify]。只写一个值时两个方向都用同一个值。
Part 4: 布局决策
Flexbox 还是 Grid?一个简单的判断标准就够了。
决策树
一维排列(导航栏、居中)→ Flexbox。二维网格(页面结构、仪表盘)→ Grid。
场景速查
六种常见场景的推荐方案和核心代码 — 遇到布局问题时直接查表。
布局决策树
问自己:我需要控制行还是列,还是两个都要?
导航栏、按钮组、居中对齐、等高列:只需要控制一行或一列的排布。
页面结构、仪表盘、复杂布局:行和列都要精确控制。
图片墙、产品列表:列数随容器宽度自动伸缩。
场景速查表
遇到具体场景时,查这张表就够了
| 场景 | 推荐方案 | 核心代码 |
|---|---|---|
| 水平/垂直居中 | Flexbox | display:flex; justify-content:center; align-items:center; |
| 导航栏 | Flexbox | display:flex; justify-content:space-between; |
| 页面整体结构 | Grid | grid-template-areas: "header header" "sidebar main"; |
| 响应式卡片列表 | Grid | repeat(auto-fit, minmax(250px, 1fr)) |
| 等高列 | Flexbox | display:flex; align-items:stretch; |
| 复杂仪表盘 | Grid | repeat(4, 1fr) + 跨行跨列 |
动手练习
Flexbox 练习
- 创建带图标的导航栏,图标与文字垂直居中
- 实现三栏布局:中间固定宽度,两侧弹性
- 用 Flexbox 实现水平垂直居中的登录表单
Grid 练习
- 用 Grid 创建 8x8 棋盘
- 实现响应式博客布局(侧边栏 + 主内容)
- 创建包含跨行列组件的仪表盘
综合练习
- 分析电商首页:哪些用 Flexbox,哪些用 Grid
- 将 float 布局的页面重构为 Flexbox/Grid
- 创建完全响应式的个人作品集页面
本章学习完毕
CSS 布局技术已经从"如何实现"发展到"如何优雅实现"。掌握 Flexbox 和 Grid,用更少的代码、更高的效率构建现代网页。