HandyTools Hub

← 全部指南

CSS Grid 详解:行列、网格区域,以及什么时候该用 Grid 而不是 Flexbox

2026-08-17

你见过 display: gridgrid-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 等价。轨道尺寸可以是固定长度(200px4rem)、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;(或 sidebarmainfooter)。布局一眼可读,做移动端断点重排时只需重写区域模板。两条规则:每个区域必须矩形(L 形非法);模板的每个格子都要填满——空位用 . 表示。

间距与对齐

间距。 gap(配 row-gap / column-gap)在轨道之间加空隙,不会在容器边缘加边距。

单元格内对齐。 justify-items(水平)和 align-items(垂直)把子项放在它自己的单元格里;默认 stretch,这正是 grid 子项填满单元格的原因。justify-self / align-self 单独覆盖某个子项。

容器内对齐网格。 当轨道比容器小时——auto 内容行常见——justify-contentalign-content 摆放整张轨道网格(取值如 centerspace-betweenspace-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-fitauto-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 21 / -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 那一半。