CSS 网格布局(Grid Layout)是 CSS 中最强大的二维布局系统。一句话概括它的定位:Flexbox 管一维(一行或一列),Grid 管二维(行和列同时控制)。页面主结构、卡片画廊、仪表盘、图片墙——凡是「横竖都要对齐」的场景,Grid 都是首选。
本文从作用、使用场景、核心语法到实战技巧,带你系统掌握 Grid 布局,所有代码可直接复制使用。
网格布局的作用
在 Grid 出现之前,做复杂的页面结构要靠 float、定位甚至表格 hack,代码冗长还难维护。Grid 的核心价值有三点:
- 二维同时控制:一个容器同时定义行轨道和列轨道,元素可以精确落在「第几行第几列」。
- 结构与内容分离:用
grid-template-areas画ASCII地图即可排版,HTML 顺序不用动,换断点时只改 CSS。 - 代码量断崖式下降:过去需要嵌套多层 div + 媒体查询的布局,现在 3~5 行 CSS 搞定。
Grid 与 Flexbox:怎么选?
两者不是替代关系,而是互补。判断标准很简单:内容排成一条线用 Flex,排成一片面用 Grid。
| 对比项 | Flexbox | Grid |
|---|---|---|
| 维度 | 一维(行或列) | 二维(行 + 列) |
| 布局起点 | 内容决定布局(content-first) | 布局决定内容位置(layout-first) |
| 典型场景 | 导航栏、按钮组、单行卡片 | 页面骨架、画廊、表格型界面 |
| 跨行/跨列 | 不支持 | span / 区域命名原生支持 |
| 空隙控制 | gap |
gap(行列分别设置) |
核心语法:定义你的第一个网格
三行代码就能建立一个 3 列等宽、带 16px 间距的网格:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}
必须记住的 4 个容器属性
| 属性 | 作用 | 示例 |
|---|---|---|
display: grid |
开启网格容器 | 直接写在父元素上 |
grid-template-columns |
定义列轨道 | 200px 1fr 1fr |
grid-template-rows |
定义行轨道 | 60px 1fr 40px |
gap |
行/列间距 | gap: 16px 24px |
fr 单位:Grid 最好用的发明
fr(fraction)表示「剩余空间的一份」。与百分比不同,fr 会自动扣除 gap 间距,配合固定宽度非常好算:
/* 侧栏固定 240px,主区与侧栏按 2:1 瓜分剩余空间 */
.layout {
display: grid;
grid-template-columns: 240px 1fr;
/* 更细的分配: */
grid-template-columns: 240px minmax(0, 2fr) 1fr;
}
1fr 约等于「自适应剩余宽度」,写布局时优先用 fr,少用百分比 + calc()。典型使用场景
场景 1:响应式卡片画廊(无需媒体查询)
auto-fit + minmax 是 Grid 最经典的组合:卡片最小 220px,容器变窄时自动减少列数,变宽时自动增列,一行 CSS 完成响应式:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
场景 2:页面骨架(Holy Grail 布局)
用 grid-template-areas 画一张「地图」,语义直观,移动端重排只需改地图:
.page {
display: grid;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 240px;
grid-template-rows: 60px 1fr 48px;
min-height: 100vh;
gap: 12px;
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
/* 移动端:改地图即可,HTML 不动 */
@media (max-width: 768px) {
.page {
grid-template-areas:
"header"
"nav"
"main"
"aside"
"footer";
grid-template-columns: 1fr;
}
}
场景 3:图片不规则拼贴
让某个项目跨行跨列,用 grid-row / grid-column 的 span 即可做出杂志风拼贴:
.mosaic {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 180px;
gap: 10px;
}
.mosaic .feature {
grid-column: span 2;
grid-row: span 2;
}
场景 4:仪表盘 / 后台表格型界面
统计卡片、图表区块这类「横竖都要对齐」的界面,Grid 比 Flex + 换行可控得多——Flex 换行后每行高度独立,无法保证纵向对齐,而 Grid 天然保证行轨道与列轨道对齐。
实战技巧清单
技巧 1:auto-fill 与 auto-fit 的区别
auto-fill:尽量塞满轨道,空轨道保留占位。auto-fit:空轨道坍缩为 0,已有项目被拉伸填满整行。- 卡片少的时候想拉伸铺满 → 用
auto-fit;想保持格子节奏 → 用auto-fill。
技巧 2:minmax(0, 1fr) 解决内容撑爆
Grid 项目默认 min-width: auto,长文本/代码会把列撑破。把最小值显式设为 0 即可让内容正常收缩:
.row {
display: grid;
grid-template-columns: 1fr minmax(0, 2fr) 1fr;
/* 或者统一处理: */
}
.row > * {
min-width: 0;
}
技巧 3:grid-auto-flow: dense 自动补洞
有跨格项目时网格会出现空洞,dense 会让后续小项目自动回填空隙,适合图片流、瀑布位:
.grid {
grid-auto-flow: row dense;
}
dense 会打乱 DOM 顺序的视觉呈现,影响键盘 Tab 焦点顺序,纯展示型网格再用。技巧 4:隐式网格与 grid-auto-rows
grid-template-* 只定义「显式轨道」,超出部分进入隐式轨道,默认高度由内容决定。用 grid-auto-rows 给隐式行统一设定基准:
.grid {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 120px; /* 第 4 行及以后自动 120px */
}
技巧 5:容器级与项目级对齐
| 层级 | 属性 | 作用 |
|---|---|---|
| 容器 | justify-items / align-items |
所有格子内容的默认对齐 |
| 容器 | justify-content / align-content |
整个网格在容器内的分布 |
| 项目 | justify-self / align-self |
单个项目在自己格子里的对齐 |
技巧 6:subgrid 对齐嵌套结构
卡片内部字段(标题/正文/按钮)想跨卡片纵向对齐?让子元素继承父网格轨道:
.card {
display: grid;
grid-row: span 3; /* 卡片占父网格 3 行 */
grid-template-rows: subgrid; /* 内部直接复用父轨道 */
}
总结
布局思维从「内容怎么排」升级为「先画网格,再放内容」——这正是 Grid 让 CSS 布局工程化的关键一步。
- 一维用 Flex,二维用 Grid,骨架用 Grid、内部用 Flex 是最佳拍档。
- 记住三板斧:
display: grid+repeat()+minmax(),80% 的布局需求即可覆盖。 - 响应式优先尝试
repeat(auto-fit, minmax(220px, 1fr)),很多场景真的不需要媒体查询。 - 内容撑爆列时,第一反应写
min-width: 0或minmax(0, 1fr)。