跳转至

Grid — 二维布局与自适应网格

这一章讲 CSS 最强的布局系统。 如果说 Flexbox 是「排好一行」, Grid 就是「画好一张表」:页眉、侧栏、主区、页脚各自落格,行列同时控制。 它还给了现代 CSS 最出名的一行代码——不写一个媒体查询的自适应网格1。

1. 这一章在全书链条里的位置

Flexbox(第 06 章)管一维,Grid 管二维——书里把 Grid 称作「CSS 里最强的布局系统」, 定位为处理整页版面和大规模布局的工具2。两章是互补不是替代: 一行导航用 Flex,整页骨架用 Grid;拿 Flex 套娃搭网格,就该换 Grid3。

2. 顶层全景:表格纸模型

把 Grid 容器想象成一张画好线的表格纸:

线1    线2    线3    线4
 ┌──────┬──────┬──────┐ 线1
 │ cell │ cell │ cell │
 ├──────┼──────┼──────┤ 线2
 │ cell │ cell │ cell │
 └──────┴──────┴──────┘ 线3
   列1    列2    列3      ← 三条「轨道」(track)

图说:线是分隔线,轨道是线之间的列/行,单元格是行列交点。
三栏网格有「四条线」——所有跨栏错误都从数错线开始。

五个名词,书里一张表4:网格容器(display: grid 的父)、网格项(直接孩子)、 轨道(两条线之间的行或列)、单元格(行列交点)、网格区域(一个或多个单元格拼成的矩形)。 外加关键单位 fr(fraction,分数):占剩余空间的几分之几5。

3. 核心原理:先画骨架,再放子项

骨架:grid-template-columns / rows

.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;      /* 三列:一列钉死,两列平分剩余 */
  grid-template-rows: repeat(3, 100px);       /* 三行,各 100px */
}

两列 1fr 1fr 把剩余空间对半分——「一个固定侧栏 + 两个弹性内容区」一行画完。 repeat(3, 100px) 是批量简写,等价于 100px 100px 100px6。 minmax(最小, 最大) 给轨道一个区间:「再小不能小于 250px,空间够就拉伸」7。

放子项:按线编号

.item {
  grid-column: 1 / 3;      /* 从线1 跨到线3 = 占第1、2两列 */
  grid-row: 2 / span 2;    /* 从线2 开始,跨两行 */
}

语法是「起线 / 止线」,止线也可以写 span 2(跨两条轨道)8。 线比栏多一:三栏网格的竖线是 1、2、3、4——所以「占前两列」写 1 / 3 而不是 1 / 2。 书里把这个列为本章常见错误的第一条9。

主线例子:圣杯布局,两个写法

输入:经典页面——页眉通栏、侧栏 200px、主区吃剩余、页脚通栏。 第一种写法,命名区域——版式本身就是一串按行列排好的文字(行话叫字符串),直接「画」出来:

.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}
.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }

grid-template-areas 的值是一张缩进的「字符画」:每行对应网格的一行, 每格写一个区域名;同名区域横向相邻就自动合并——header 出现两次,页眉就通栏10。 子项用 grid-area: 名字 各就各位。改版式只动字符串,这是 Grid 最有可读性的玩法。

自适应网格:最出名的一行

.auto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1rem;
}

走一遍这条规则的语义(数字是为演示设的):容器 1100px 宽、间距 16px—— 每列至少 250px:放 4 列需要 250×4 + 16×3 = 1048px,放得下;放 5 列需要 250×5 + 16×4 = 1314px,放不下——所以是 4 列,每列分得 (1100 − 48) ÷ 4 = 263px。容器缩到 800px,重算一遍:3 列(250×3+16×2=782 ≤ 800), 每列约 256px;缩到 500px,就剩 2 列。列数永远自动,一行媒体查询都不用写11。

auto-fit 是「能放几列就放几列,空列折叠」;把 fr 设成上限(1fr), 多余空间平分回现有列上——这就是「自动填充 + 拉伸」两个愿望一次满足的来源。

单格对齐与隐式网格

justify-self / align-self 让某个子项在自己的格子里偏左偏上(取值 start/end/center/stretch)12。 隐式网格:子项放到了声明的骨架之外,浏览器自动补轨道——用 grid-auto-rows/grid-auto-columns 控制补出来的轨道尺寸13。

4. 常见模式速览

书里给的模式,上面已经走完全部两个重头(圣杯、自适应网格),再补一条间距规矩: 轨道间距用 gap,别用百分比——fr 会自动把 gap 算进分配,百分比不会, 容易溢出14。

5. 作者的判断与证据

  • 「Grid 是最强的布局系统」——定位断言(带 arguably 式保留)2。
  • 「一维用 Flex、二维用 Grid」——分工判断,第 06 章同一句从对面又说一遍3。
  • 「3 列网格有 4 条线」——几何事实,作为防错提示给出9。
  • 「auto-fit + minmax 是最流行的现代网格模式」——流行度断言,符合当前业界观察1。
  • 证据类型同全书:断言 + 最小例子。

6. 边界与局限

  • 没讲 grid-auto-flow(子项自动排位的方向与稠密模式)、place-items 简写等二线属性。
  • 没讲 subgrid(子网格,2023–2024 年陆续落地)——卡片内容对齐网格的利器,本书未收。
  • 隐式网格只给了一行;fit-content、命名线([sidebar-start])等进阶写法未提。
  • 自适应网格那行没解释 auto-fill 与 auto-fit 的差别(空轨是否折叠), 是「能跑但不全懂」的一处。

判断(我们的,不是书里的): 本章的讲法顺序(名词 → 骨架 → 放子项 → 模式)是对的, 但最值得单独立起来的是「线 vs 栏」这个计数模型——它是 Grid 唯一违反直觉的地方, 其余一切(区域、fr、auto-fit)都顺着常识走。把 1 / 3 背成「从第 1 线到第 3 线」而不是「占第 1 到 3 列」, 后续永远不数错。 如果错,会错在: 对从表格时代过来的老开发者,「线模型」反而需要额外解释 (他们习惯 rowspan/colspan 的「占几格」思路)——但对零基础读者,线模型是一手建立、无历史包袱的。

7. 可带走的

  1. display: grid 开二维世界;骨架 = grid-template-columns + grid-template-areas10。
  2. fr 分剩余空间:200px 1fr 1fr = 钉死一列、其余对半5。
  3. 放子项按线编号:grid-column: 1 / 3;线比栏多一,三栏四线9。
  4. 命名区域是 Grid 最好读的玩法:字符串画版式,同名自动合并10。
  5. repeat(auto-fit, minmax(250px, 1fr)) 一行自适应,记住 1100px→4 列(263px 每列)这个演算11。
  6. 间距用 gap,不用百分比14。
  7. 子项出格了会有隐式轨道,grid-auto-rows 管它的尺寸13。

8. 原文地图

主题 原书章 原文位置
最强布局系统定位 Chapter 8: Grid Layout Reference text/09-ch01-1-chapter-overview.txt:7(搜「most powerful」)
容器/项/轨道/单元格/区域 同上 text/09-ch01-1-chapter-overview.txt:23(搜「space between two grid lines」)
fr 单位 同上 text/09-ch01-1-chapter-overview.txt:29(搜「Fractional Unit」)
repeat 与 minmax 同上 text/09-ch01-1-chapter-overview.txt:47(搜「repeat(count, size)」)
骨架示例 200px 1fr 1fr 同上 text/09-ch01-1-chapter-overview.txt:55(搜「One fixed, two flexible」)
grid-template-areas 同上 text/09-ch01-1-chapter-overview.txt:59(搜「grid-template-areas」)
grid-column 的 1 / 3 与 span 同上 text/09-ch01-1-chapter-overview.txt:89(搜「Starts at line 1」)
圣杯布局 同上 text/09-ch01-1-chapter-overview.txt:107(搜「Holy Grail」)
auto-fit minmax 自适应网格 同上 text/09-ch01-1-chapter-overview.txt:128(搜「minmax(250px, 1fr)」);:132 搜「fit as many」
三栏四线 同上 text/09-ch01-1-chapter-overview.txt:136(搜「4 grid lines」)
一维别用 Grid 同上 text/09-ch01-1-chapter-overview.txt:138(搜「one-dimensional」)
间距别用百分比 同上 text/09-ch01-1-chapter-overview.txt:140(搜「Percentage vs. fr」)
隐式网格 同上 text/09-ch01-1-chapter-overview.txt:142(搜「Implicit」)

  1. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:124,搜「most popular modern grid pattern」)。原文:「The most popular modern grid pattern: creating a grid that automatically adds columns based on available space without media queries.」 ↩↩

  2. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:7,搜「most powerful」)。原文:「The CSS Grid Layout Module is the most powerful layout system available in CSS.」 ↩↩

  3. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:138,搜「one-dimensional」)。原文:「Don't use Grid for simple one-dimensional rows (use Flexbox instead). Use Grid when you need to align items in both directions.」 ↩↩

  4. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:23,搜「space between two grid lines」)。原文:「The space between two grid lines (essentially a row or a column).」 ↩

  5. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:29,搜「Fractional Unit」)。原文:「A flexible unit that represents a fraction of the available space in the grid container.」 ↩↩

  6. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:55,搜「One fixed, two flexible」)。原文示例:grid-template-columns: 200px 1fr 1fr; 与 grid-template-rows: repeat(3, 100px);。 ↩

  7. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:49,搜「minmax(min, max)」)。原文:「Defines a size range.」 ↩

  8. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:89,搜「Starts at line 1」)。原文示例:grid-column: 1 / 3; /* Starts at line 1, ends at line 3 */、grid-row: 2 / span 2;。 ↩

  9. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:136,搜「4 grid lines」)。原文:「Remember that lines are the "dividers." A 3-column grid has 4 grid lines.」 ↩↩↩

  10. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:59,搜「grid-template-areas」;:107 搜「Holy Grail」)。原文:「Defines a grid template by referencing names of grid areas.」圣杯示例的字符串布局见第 64–70 与 110–117 段。 ↩↩↩

  11. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:126,搜「auto-grid」;:132 搜「fit as many」)。原文:grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));,输出解释:「The browser will fit as many 250px columns as possible. If there is extra space, they will all grow equally (1fr).」行文中 1100px/800px/500px 三种容器宽度与算出的列数,是为演示演算编的数,演示规则本身。 ↩↩

  12. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:100,搜「justify-self」)。原文:「Aligns a single grid item within its cell.」 ↩

  13. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:142,搜「Implicit」)。原文:「If you place an item outside the defined grid-template, the browser creates 'Implicit' tracks. You can control their size using grid-auto-rows or grid-auto-columns.」 ↩↩

  14. 出处:「Chapter 8: Grid Layout Reference」(text/09-ch01-1-chapter-overview.txt:140,搜「Percentage vs. fr」)。原文:「Avoid using % for grid gaps. Use the fr unit instead; it automatically accounts for the gap size, whereas percentages often lead to overflow.」 ↩↩