CSS Grid 详解:行列、网格区域,以及什么时候该用 Grid 而不是 Flexbox
2026-08-17
你见过 display: grid 和 grid-template-columns: repeat(3, 1fr),但第一次真正搭建页面布局时,各块并没有按你想象的方式拼合。Grid 是 CSS 史上最强大的布局系统——也是与之前一切最不同的。一旦你内化了几个心智模型——轨道、网格线、区域和隐式网格——剩下的就都是可以随时查的细节。本文从零搭起这些模型。
Grid 是二维的
这一句话就是 grid 存在的全部理由:flexbox 一次只沿一根轴布局;grid 一开始就同时定义行和列。 flex 容器在子项到达时逐步算出布局;grid 容器则是一张固定的单元格表格,子项被放进格子里。本指南其余内容都是这句话的推论——包括选哪一个的决定(简版:页面骨架和卡片网格用 grid;沿一条线分布一组东西用 flexbox)。
轨道:行与列
grid 的行和列就是它的轨道,由两条声明创建:
display: grid;
grid-template-columns: 200px 1fr 1fr; /* 三条列轨道 */
grid-template-rows: 100px auto; /* 两条行轨道 */
repeat(3, 1fr) 与三个 1fr 等价。轨道尺寸可以是固定长度(200px、4rem)、auto(按内容)、百分比,或 fr 分数——后者值得单独一节。
分隔并环绕轨道的线叫网格线,从 1 开始编号:三列产生四条竖线。放置子项时会用到线号。
fr 单位与轨道尺寸的算法
fr 是剩余空间的一份——不是长度,也不是百分比。这是最容易被误解的 grid 值:
- 浏览器先放置固定和
auto轨道。 - 剩下的空间再按比例分给各
fr轨道。
所以 1fr 1fr 1fr 是”固定轨道排完后所剩空间”的三等份,1fr 1fr 2fr 让第三列拿到其他两列的两倍。两个值得内化的推论:
1fr不等于1px或任何固定宽度——它是”剩余的一份”。fr轨道不会像100%轨道那样撑破容器。1fr 1fr遇到内容很重的轨道可以优雅收缩;50% 50%加上大gap或很宽的内容就可能溢出边界。
minmax() 给轨道加上下限和上限:minmax(200px, 1fr) 意为”至少 200px,然后长满剩余空间”——下面响应式布局的基本积木。
放置子项:网格线、跨度和区域
grid 子项默认按源码顺序自动放进单元格,逐行填充——很多布局到此就够了。要精确控制,就按线号放置:
grid-column: 1 / 3; /* 从线 1 到线 3 → 跨两列 */
grid-row: 1 / 2;
取值是 起始 / 结束 线号。三列有四条线,所以 1 / 3 表示”第 1、2 两列”。不想数线时用跨度语法更友好:grid-column: span 2 意为”从落点起占两列”。1 / -1 是常用惯用法,意为”从第一条到最后一列线”——比如横跨全宽的页头。
更复杂的场景用命名区域,可读性最好。
grid-template-areas:用 ASCII 排布页面
命名区域让你用一条形似 ASCII 的声明描述整页结构:
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
每个子项用一行认领槽位:grid-area: header;(或 sidebar、main、footer)。布局一眼可读,做移动端断点重排时只需重写区域模板。两条规则:每个区域必须矩形(L 形非法);模板的每个格子都要填满——空位用 . 表示。
间距与对齐
间距。 gap(配 row-gap / column-gap)在轨道之间加空隙,不会在容器边缘加边距。
单元格内对齐。 justify-items(水平)和 align-items(垂直)把子项放在它自己的单元格里;默认 stretch,这正是 grid 子项填满单元格的原因。justify-self / align-self 单独覆盖某个子项。
容器内对齐网格。 当轨道比容器小时——auto 内容行常见——justify-content 和 align-content 摆放整张轨道网格(取值如 center、space-between、space-evenly)。如果 grid 莫名留出空白,通常是轨道没填满容器,用这两者之一调节。
隐式网格与响应式绝招
把子项放到已声明轨道之外,grid 会即时创建新轨道——这就是隐式网格。默认尺寸是 auto(按内容),也可以控制:grid-auto-rows: 100px 让每条自动创建的行都是 100px 高;grid-auto-flow: dense 让后面的子项回填前面留下的空洞。
支撑无数响应式布局的绝招:
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
读作:“能放几列就放几列,每列在 200px 到一行的一份之间;空的列折叠掉。“一条声明就让卡片网格从宽屏的三列流畅过渡到手机的整列——完全不用媒体查询。细节在于 auto-fit 和 auto-fill 的区别:auto-fit 会折叠没有子项的轨道(所以行永远显得填满),auto-fill 则保留空轨道、可能留下空白。做卡片网格时,几乎总是用 auto-fit。
Grid 还是 Flexbox:怎么选
- Grid——布局的行和列必须彼此协调时:页面骨架、卡片网格、仪表盘,以及任何你可以在内容到达前画出单元格表格的场景。
- Flexbox——沿一根轴分布或对齐一组东西时:导航栏、工具栏、按钮行、图标挨着两行文字。
两者不是对手,而是互补。常见架构是 grid 搭页面骨架,flexbox 在每个单元格内部做精细对齐。还在犹豫的话,CSS Flexbox 详解讲了这种决策的一维那一侧。
速查
- Grid 一开始就定义行和列;flexbox 一次只排一根轴。
fr= 剩余空间的一份,不是长度——先排固定/auto轨道,fr分剩下的。minmax(200px, 1fr)= “至少 200px,然后长满”。grid-column: 1 / 3把子项放在线 1 到线 3 之间;span 2和1 / -1是顺手变体。grid-template-areas用 ASCII 排布页面;区域必须矩形,.是空格。justify-items/align-items把子项放进自己的格子(默认stretch);justify-content/align-content把轨道网格摆进容器。repeat(auto-fit, minmax(200px, 1fr))= 无需媒体查询的响应式卡片网格。- 二维用 grid;一条线上的子项用 flexbox。
想可视化设计 grid?CSS Grid Generator 让你拖拽出行、列和区域并直接复制成品 CSS;CSS Flexbox Generator 则覆盖布局工具箱里的 flexbox 那一半。