CSS Handbook · 布局

第六章 / 6.4 Grid 详解

第六章 · 6.4 节

Grid 详解


如果说 Flexbox 是"一维"的排布工具,那 Grid 就是真正意义上的"二维"布局系统——它能同时控制行与列,让我们第一次可以用纯 CSS 精确描述报刊式的复杂版面,而不必依赖嵌套的 div 拼凑。

与 Flexbox 的分工

FlexboxGrid
维度一维(一行或一列)二维(行与列同时)
驱动方式内容驱动,尺寸由内容撑开布局驱动,先定义轨道再放内容
典型场景导航栏、按钮组、卡片内部排布页面整体骨架、图片墙、杂志排版

实战中二者并非互斥:常见做法是用 Grid 搭建页面级的整体骨架,再用 Flexbox 处理骨架内部每个区块的一维排列。

定义行与列

.layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 64px 1fr 48px;
  gap: 16px;
}

grid-template-columns / grid-template-rows 用空格分隔的一串长度值定义"轨道"(track),每个值对应一条列或一行的尺寸。轨道之间天然形成"网格线"(grid line),从 1 开始编号,也可以用 repeat() 简化重复轨道:

.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
效果预览:4 列等宽网格
1
2
3
4

fr 单位

fr(fraction)是 Grid 专属的弹性单位,代表"分配剩余空间的份数",与 flex-grow 的思路相通,但更灵活——可以与固定长度混用:

.layout {
  grid-template-columns: 200px 1fr 2fr;
  /* 第一列固定 200px,剩余空间按 1:2 分给第二、三列 */
}

子项定位

子项可以用网格线编号,精确指定自己横跨的起止位置:

.hero {
  grid-column: 1 / 3;   /* 从第 1 条线到第 3 条线,横跨 2 列 */
  grid-row: 1 / 2;
}
/* span 关键字:横跨 N 条轨道,无需关心起止编号 */
.wide { grid-column: span 2; }
效果预览:第二项横跨两列
1
span 2
3
4

grid-template-areas:具名区域

把网格划分成语义化的命名区域,是 Grid 中最具可读性的用法——布局结构在 CSS 里"画"出来,一目了然:

.page {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main"
    "sidebar footer";
}
.sidebar { grid-area: sidebar; }
header   { grid-area: header; }
main     { grid-area: main; }
footer   { grid-area: footer; }
提示每一行字符串的单词个数必须与列数一致;用连续的点号 . 可以留出空白区域,不分配给任何子项。

auto-fit / auto-fill / minmax:自适应网格

这是 Grid 中最强大的组合技,能实现"不写媒体查询也能响应式"的卡片网格——根据容器宽度自动决定放几列。

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

minmax(200px, 1fr) 表示每列最小 200px、最大均分剩余空间;auto-fit 会自动计算能放下几列,并让已有列拉伸填满整行;auto-fill 则会保留"看不见"的空轨道位置,列不会被拉伸得过宽。二者的区别只有在剩余空间不足以再放一列时才会体现出来。

空间足够放下更多列时
auto-fit已有列拉伸,填满整行,不留空轨道
auto-fill保留潜在空轨道的位置,已有列不额外拉伸

隐式网格

当子项数量超出 grid-template-* 定义的轨道数时,浏览器会自动生成"隐式轨道"来容纳多出的内容。用 grid-auto-rows / grid-auto-columns 控制这些隐式轨道的尺寸,grid-auto-flow: dense 则会让排布算法主动回填此前跳过的空隙。

.masonry-like {
  grid-auto-rows: 10px;
  grid-auto-flow: dense;
}

对齐属性总览

Grid 的对齐属性与 Flexbox 一脉相承,但多了"针对整个网格"与"针对单个子项"两个维度:

属性作用对象方向
justify-items所有子项行内方向(水平)
align-items所有子项块方向(垂直)
justify-self单个子项,覆盖 justify-items行内方向
align-self单个子项,覆盖 align-items块方向
justify-content整个网格(当轨道总宽小于容器时)行内方向
align-content整个网格块方向

实战:杂志式排版

结合具名区域、span 与 auto-fit,可以快速搭出一个左侧特写、右侧信息流的版面:

.magazine {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-template-rows: repeat(3, auto);
  gap: 16px;
}
.feature { grid-row: span 3; } /* 左侧特写纵跨三行 */
效果预览
特写
条目 1
条目 2
条目 3

Chapter 6 · Section 6.4

Grid in Depth


If Flexbox is a "one-dimensional" arrangement tool, then Grid is a truly "two-dimensional" layout system — it controls rows and columns at the same time, letting us describe complex newspaper-style layouts with pure CSS for the first time, without nesting divs to fake it.

How Grid Complements Flexbox

FlexboxGrid
DimensionsOne-dimensional (a row or a column)Two-dimensional (rows and columns at once)
Driving modelContent-driven; sizes expand from contentLayout-driven; define tracks first, then place content
Typical use casesNavbars, button groups, internal card layoutOverall page skeleton, image walls, magazine layouts

In practice the two are not mutually exclusive: the common approach is to build the page-level skeleton with Grid, then use Flexbox for the one-dimensional arrangement inside each block of that skeleton.

Defining Rows and Columns

.layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-rows: 64px 1fr 48px;
  gap: 16px;
}

grid-template-columns / grid-template-rows define "tracks" with a space-separated list of lengths, each value being the size of one column or row. Between tracks, "grid lines" form naturally, numbered starting from 1; repeat() can also simplify repeated tracks:

.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
Preview: a 4-column equal-width grid
1
2
3
4

The fr Unit

fr (fraction) is a flexible unit exclusive to Grid, meaning "a share of the remaining space". It works on the same idea as flex-grow but is more flexible — it can be mixed with fixed lengths:

.layout {
  grid-template-columns: 200px 1fr 2fr;
  /* the first column is fixed at 200px; remaining space is split 1:2 between columns 2 and 3 */
}

Placing Items

Items can use grid line numbers to precisely specify where they start and end:

.hero {
  grid-column: 1 / 3;   /* from line 1 to line 3, spanning 2 columns */
  grid-row: 1 / 2;
}
/* the span keyword: spans N tracks without caring about start/end numbers */
.wide { grid-column: span 2; }
Preview: the second item spans two columns
1
span 2
3
4

grid-template-areas: Named Areas

Dividing the grid into semantically named areas is Grid's most readable feature — the layout structure is "drawn" in the CSS, instantly clear:

.page {
  display: grid;
  grid-template-columns: 220px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main"
    "sidebar footer";
}
.sidebar { grid-area: sidebar; }
header   { grid-area: header; }
main     { grid-area: main; }
footer   { grid-area: footer; }
TipEach row of strings must have as many words as there are columns; consecutive dots . leave an empty area that is assigned to no item.

auto-fit / auto-fill / minmax: Adaptive Grids

This is Grid's most powerful combination, achieving a card grid that is "responsive without writing media queries" — the number of columns is decided automatically from the container's width.

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

minmax(200px, 1fr) means each column is at least 200px and at most an equal share of the remaining space; auto-fit automatically works out how many columns fit and stretches existing columns to fill the whole row; auto-fill keeps the positions of "invisible" empty tracks, so columns do not get stretched too wide. The difference only shows up when there is not enough leftover space for another column.

When there is room for more columns
auto-fitExisting columns stretch to fill the row; no empty tracks are left
auto-fillPositions of potential empty tracks are kept; existing columns are not stretched extra

The Implicit Grid

When the number of items exceeds the tracks defined by grid-template-*, the browser automatically generates "implicit tracks" to hold the extra content. Use grid-auto-rows / grid-auto-columns to control the size of these implicit tracks, and grid-auto-flow: dense makes the placement algorithm actively backfill gaps it skipped earlier.

.masonry-like {
  grid-auto-rows: 10px;
  grid-auto-flow: dense;
}

Alignment Properties at a Glance

Grid's alignment properties are inherited from Flexbox, but add two extra dimensions: "for the whole grid" and "for a single item":

PropertyApplies toDirection
justify-itemsAll itemsInline direction (horizontal)
align-itemsAll itemsBlock direction (vertical)
justify-selfA single item, overrides justify-itemsInline direction
align-selfA single item, overrides align-itemsBlock direction
justify-contentThe whole grid (when the total track width is smaller than the container)Inline direction
align-contentThe whole gridBlock direction

In Practice: A Magazine-Style Layout

Combining named areas, span, and auto-fit, you can quickly build a layout with a feature on the left and an info stream on the right:

.magazine {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-template-rows: repeat(3, auto);
  gap: 16px;
}
.feature { grid-row: span 3; } /* the feature on the left spans three rows */
Preview
Feature
Item 1
Item 2
Item 3