Skip to content

grid 布局 ​

CSS Grid 是浏览器原生的二维布局系统:一次性掌控行与列。它把容器切成网格轨道(tracks),再把子元素按「线 / 区域 / 自动流」放入格子,天然适合栅格系统、卡片墙、页面框架、自适应换行等复杂布局。本文按「基础篇 → 进阶篇 → 实战篇」循序展开,每章配可运行的在线演示,读完即可上手真实业务 UI。

导航目录 ​

基础篇 · 建立网格心智模型 ​

进阶篇 · 精准放置与自适应 ​

实战篇 · 定位、栅格与练习 ​

概述 ​

网格布局(CSS Grid)是强大的二维布局方案:同时控制行(row)与列(column)。它把容器划分为网格轨道(tracks),再把子元素放入指定的网格区域,从而实现复杂布局(栅格系统、卡片列表、自适应换行、区域拼接等)。

  • 二维布局:Flex 更擅长“一维”(一行或一列)的排列;Grid 更擅长“二维”(行+列)的整体排布。
  • 核心思路:先定义网格(行/列轨道)→ 再放置网格项(按线、按区域、自动布局)。

一句话抓住核心

Grid 的一切都围绕两步展开:① 在容器上定义网格结构(有多少行、多少列、多大);② 在子项上决定它落在哪个格子/区域。看到任何 Grid 属性,先判断它属于「定义结构」还是「放置元素」,思路立刻清晰。

基础概念:行(rows)与列(columns) ​

Grid 网格由行与列共同组成:

  • 行(rows):通常由 grid-template-rows 定义,控制每一行的高度。
  • 列(columns):通常由 grid-template-columns 定义,控制每一列的宽度。

补充两个常见概念:

  • 网格线(grid lines):行/列的分界线,编号从 1 开始;元素可以通过线编号进行放置。
  • 网格单元(cell)/网格区域(area):单元是最小格子;区域可以由多个单元合并组成。

记住「线」而不是「格子」

放置元素时,grid-column: 1 / 3 指的是从第 1 根线到第 3 根线(横跨 2 个格子),而不是「第 1 到第 3 个格子」。初学者最常在这里绕晕——凡涉及 grid-row / grid-column 的数字,一律理解为线编号。

定义网格:fr 单位与等分布局 ​

fr 是 Grid 的“剩余空间分配单位”(fraction)。当列/行使用 fr 时,会在扣除固定宽度与间隙后,将剩余空间按比例分配。

  • 常见写法:grid-template-columns: 1fr 1fr 1fr;(三列等分)
  • 混合写法:200px 1fr 2fr(先固定,再按比例分配剩余空间)

合并区域:grid-template-areas 与区域命名 ​

当布局更像“页面区域拼图”(header / sidebar / content / footer)时,推荐使用 grid-template-areas:

  • 可读性强:用字符串直观看到布局结构
  • 适合大块区域:尤其是典型页面框架布局

注意:区域命名需要配合子元素的 grid-area 使用。

网格间隙及简写 ​

网格轨道之间的间距用 gap 控制(以前常见写法是 grid-gap,现在统一推荐 gap)。

  • 统一间隙:gap: 16px;
  • 分别设置行/列间隙:row-gap: 12px; column-gap: 20px;
  • 简写(行 列):gap: 12px 20px;

网格对齐方式及简写 ​

Grid 的对齐分两类,容易混淆:

  • 容器层(整张网格在容器里的对齐):justify-content(水平)/ align-content(垂直)
  • 单元层(网格项在单元格里的对齐):justify-items(水平)/ align-items(垂直)

同时提供简写:

  • place-content: <align-content> <justify-content>;
  • place-items: <align-items> <justify-items>;
  • 单个元素还可用 justify-self / align-self 覆盖自身对齐。

显式网格与隐式网格 ​

显式网格(Explicit Grid)是你通过 grid-template-rows / grid-template-columns 明确声明的轨道数量。当网格项数量或放置位置超出显式范围时,浏览器会自动创建隐式网格(Implicit Grid),其轨道尺寸由 grid-auto-rows / grid-auto-columns 决定。

显式 vs 隐式:谁生成的?

  • 显式:你亲手写出来的行列(如 3 行 2 列 = 6 个显式格子)。
  • 隐式:项目放不下时浏览器「自动补」的轨道,默认高度为 auto(内容撑开),可用 grid-auto-rows 统一控制其大小。

下图展示「定义 3 行 2 列(6 格)后放入第 7 个元素」触发隐式轨道的过程:

text
定义 grid-template:3 行 × 2 列
        │
        ▼
   生成 6 个显式格子
        │
   网格项数量 > 6 ?
    ┌───┴────┐
   否        是
    │         │
全部落入   浏览器自动创建隐式轨道
显式网格        │
          隐式轨道高度由 grid-auto-rows 决定

基于线的元素放置 ​

在显式网格里,可以直接用网格线编号把元素「钉」到指定区间,常用属性:

  • grid-column: <start> / <end>;
  • grid-row: <start> / <end>;

关键点:start 与 end 指的是“线”,不是“格子”。例如 grid-column: 1 / 3 = 从第 1 根线到第 3 根线,横跨 2 列。

负数线编号:从末尾倒数

线编号也支持负数:-1 表示最后一根线。grid-column: 1 / -1 是「占满整行」的经典写法,无需关心总列数,非常适合做页头 / 页脚这类通栏区域。

基于线的命名元素放置 ​

除了数字编号,也可以给网格线命名,然后按名称放置,更利于维护复杂布局:

  • 在 grid-template-columns/rows 中用 [] 命名网格线
  • 子项用 grid-column: left / right; 这样的方式引用

基于线的 span,行/列占用网格 ​

span 表示“跨越多少个轨道”,更适合做可复用的栅格规则:

  • grid-column: span 2; 表示从自动放置的位置开始,横向跨 2 列
  • grid-row: 2 / span 3; 表示从第 2 根行线开始,跨 3 行

repeat():减少重复声明 ​

当轨道重复出现时,用 repeat() 更清晰:

  • repeat(3, 1fr) 等价于 1fr 1fr 1fr
  • repeat(12, 1fr) 常用于 12 栅格系统

repeat 还能接可变关键字

repeat() 的第一个参数除了固定数字,还能传 auto-fill / auto-fit(见下方自适应换行)——这正是 Grid 响应式布局的关键组合。

minmax():定义轨道的最小/最大值 ​

minmax(min, max) 用于限制轨道尺寸范围,常用于自适应布局:

  • minmax(200px, 1fr):最小 200px,空间足够时再按 fr 扩展
  • 搭配 auto / max-content / min-content 可以实现内容驱动的布局策略

repeat() + minmax():自适应换行布局(auto-fill / auto-fit) ​

这是一组非常常用的响应式写法(卡片列表、图片墙等):

  • auto-fill:尽可能“填满”轨道,即使某些轨道为空也保留占位
  • auto-fit:尽可能“贴合”内容,把空轨道折叠,让已有列拉伸占满

两者在「容器很宽、内容不够填满」时差异最明显:

text
        容器变宽·可容纳更多列
                │
              关键字
        ┌───────┴────────┐
   auto-fill          auto-fit
        │                │
保留空轨道占位     折叠空轨道
已有卡片不拉伸     已有卡片拉伸铺满

一个典型例子:

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

响应式卡片墙「黄金一行」

grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); 一行即可实现「不写媒体查询的响应式」:屏幕够宽就多排几列、每列不小于 240px,屏幕变窄自动减列换行。日常卡片列表、图片墙首选此写法。

网格模拟定位 ​

通过精确控制网格线区间,可以实现类似“定位”的效果(但仍保留 Grid 的对齐与自适应能力)。适合做规则化的“拼版布局”。

span / grid-area 组合写法 ​

grid-area 是一个简写:

  • grid-area: row-start / column-start / row-end / column-end;

当你需要同时控制行与列的跨度时,它会比分别写 grid-row/grid-column 更集中。

别记错四值顺序

grid-area 的四个值顺序是 行始 / 列始 / 行终 / 列终(row-start / column-start / row-end / column-end),是「先行后列」的交替顺序,极易和 margin「上右下左」的顺时针直觉搞混。写错会导致元素跳到意料之外的格子。

栅格系统 ​

Grid 很适合做“栅格系统”(类似设计稿中的列网格)。常见做法是定义固定列数(如 12 列),再让元素按列跨度占位。

grid 布局练习一 ​

练习题建议关注:

  • 是否能用区域命名提升可读性(grid-template-areas)
  • 是否能用 repeat() / minmax() 让布局更弹性

grid 布局练习二(仿小米商城菜单) ​

这个练习更贴近真实业务 UI,建议重点练:

  • 网格项对齐(place-items/place-content)
  • 隐式网格带来的高度控制(grid-auto-rows)
  • 复杂结构时如何避免“魔法数字”的网格线编号(考虑命名线或区域)

结语 ​

一张速查表带走 Grid

  • 定结构:grid-template-columns/rows 定轨道,fr 等分、repeat() 去重复、minmax() 限范围、gap 控间隙。
  • 放元素:按线(grid-column/row + 线编号,-1 通栏)、按区域(grid-template-areas + grid-area)、按跨度(span)。
  • 管对齐:容器层 justify/align-content,单元层 justify/align-items,简写 place-*。
  • 做响应式:repeat(auto-fit, minmax(240px, 1fr)) 一行搞定卡片墙。

选型口诀:一维排列用 Flex,二维拼版用 Grid,两者常常配合使用。