文章

Grid网格布局深度解析

CSS Grid 二维布局:用 grid-template 先画"格子"再用 grid-area 放内容, fr/minmax/auto-fit 让响应式网格一行搞定,是页面级框架布局的首选。

Grid网格布局深度解析

一句话概括

Grid 是 CSS 里唯一真正的二维布局系统:同时控制行和列。Flex 是一维(一条线),Grid 是二维(一张网)——这正是它适合页面框架、仪表盘、表格的原因。

面试价值很高:Grid vs Flex 的选择是高频题;grid-template-areas 画地图式布局、auto-fit 自适应网格都是能拉开差距的亮点。

核心思路转变:从 Flex 的”排元素”变成 Grid 的”先画格子、再填内容“。最佳实践组合是——Grid 搭页面框架,Flex 排组件内部。

核心知识点

1. 核心概念:线 / 轨道 / 单元格 / 区域

  • Grid Container:设了 display: grid 的元素。
  • Grid Line(网格线):分隔线,从 1 开始编号(N 列就有 N+1 条列线)。
  • Grid Track(轨道):两条相邻线之间的行或列。
  • Grid Cell(单元格):一个行轨道 × 一个列轨道。
  • Grid Area(区域):任意矩形区域(可跨多格)。

2. 定义网格:grid-template + fr + minmax + repeat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="demo">
  <div class="g fixed">100px</div><div class="g fixed">200px</div><div class="g grow">1fr</div>
  <div class="g">1/3</div><div class="g">1/3</div><div class="g">1/3</div>
  <div class="g">auto-fill 自适应</div><div class="g">自适应</div><div class="g">自适应</div>
</div>

<style>
.demo {
  display: grid; gap: 8px; font-family: sans-serif; margin-bottom: 8px;
  grid-template-columns: 100px 200px 1fr;
}
.g { background: #3498db; color: #fff; padding: 16px 8px; text-align: center; border-radius: 6px; font-size: 13px; }
</style>

<!-- 自适应版本:容器变窄自动减列 -->
<div class="demo auto">
  <div class="g">卡片</div><div class="g">卡片</div><div class="g">卡片</div><div class="g">卡片</div>
</div>
<style>
.demo.auto { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
</style>
  • fr:剩余空间的一份。先算完所有固定列/内容列,再把”剩下的”按 fr 比例分配。
  • minmax(100px, 1fr):最小 100px,最大吃满剩余空间。
  • repeat(auto-fit, minmax(150px, 1fr)):列数随容器宽度自动增减(响应式网格一行搞定)。
  • auto-fill vs auto-fit:auto-fill 尽可能多建轨道(容器宽但项目少时右侧留空位);auto-fit 会折叠空轨道,让已有项目拉伸填满——要做”项目少也铺满”用 auto-fit。

3. 模板布局:grid-template-areas 画地图

用”画地图”的方式在 CSS 里声明布局,HTML 结构完全不用改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<div class="page">
  <header>Header</header>
  <nav>Nav</nav>
  <main>Main</main>
  <aside>Aside</aside>
  <footer>Footer</footer>
</div>

<style>
.page {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
  grid-template-rows: 80px 1fr 60px;
  grid-template-areas:
    "header header header"
    "nav    main   aside"
    "footer footer footer";
  gap: 10px; min-height: 360px;
}
header { grid-area: header; background: #e74c3c; }
nav    { grid-area: nav;    background: #3498db; }
main   { grid-area: main;   background: #2ecc71; }
aside  { grid-area: aside;  background: #f39c12; }
footer { grid-area: footer; background: #9b59b6; }
.page > * { display: flex; align-items: center; justify-content: center; color: #fff; border-radius: 6px; }
</style>
  • 地图里每个名字对应一个 grid-area;. 表示那个单元格【故意留空】,不属于任何区域。
  • 响应式只需换一套 grid-template-areas(比如手机变单列),HTML 一行不动——布局与结构解耦。

4. 网格线放置与 span

不写名字,直接用线编号精确摆放,或用 span 跨格:

1
2
3
4
5
.item {
  grid-column: 1 / 3;        /* 从第 1 条列线到第 3 条,占 2 列 */
  grid-row: 1 / -1;          /* -1 = 最后一条线,占满所有行 */
  grid-column: 2 / span 3;   /* 从第 2 线起跨 3 列 */
}

5. 隐式网格:grid-auto-rows / grid-auto-columns

当项目超出显式定义的轨道,Grid 会自动创建隐式轨道:

1
2
3
4
.container {
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 80px;   /* 自动生成的行,高 80px */
}

6. 对齐:justify/align items vs content

常和 Flex 搞混,关键看”作用对象”:

作用对象水平垂直
单元格内的项目justify-itemsalign-items
整个网格在容器内justify-contentalign-content

只有轨道总尺寸小于容器时,justify-content / align-content 才看得出效果。

其实你每天都在用

  • 后台仪表盘(header/sidebar/main/footer) → grid-template-areas 一张地图搞定。
  • 卡片墙自动按宽度换行且等宽 → repeat(auto-fit, minmax(200px, 1fr))。
  • 三栏 / 两栏页面框架 → 显式 grid-template-columns。
  • 图片画廊不规则拼接 → grid-column / grid-row 跨线。
  • 表单”标签 + 输入框”两列对齐 → Grid 比 Flex 更直观。
  • 响应式重排(手机变单列) → 只改 grid-template-areas。

常见误解(FAQ)

❌ 误区一:”Grid 比 Flex 更先进,应该全都用 Grid”

错。Flex 适合一维(导航、标签、一组按钮),Grid 适合二维(页面框架、表格、仪表盘)。真实项目是”Grid 搭框架 + Flex 排组件”混用,不是二选一。

❌ 误区二:”auto-fill 和 auto-fit 没区别”

有。auto-fill 保留空轨道(容器宽、项目少时右侧留空);auto-fit 折叠空轨道,让已有项目拉伸填满。要”项目少也铺满”用 auto-fit。

❌ 误区三:”grid-template-areas 里的 . 是占位内容”

. 表示那个单元格【故意留空】,不属于任何命名区域。它是”此地无银”的语义,不是装饰。

❌ 误区四:”fr 单位跟 % 差不多”

不同。% 直接按容器比例定宽;fr 是在扣除所有固定列 / 内容列之后,对【剩余空间】按比例分配。混合布局里 fr 比 % 更符合直觉。

❌ 误区五:”justify-items 和 justify-content 分不清”

记住作用对象:items 管”每个项目在它自己格子里怎么摆”,content 管”整张网格在容器里怎么摆”。容器比网格大时才看得出 content 的效果。

一句话总结

Grid 把布局从”嵌套 div 地狱”变成”画一张格子地图”:先 grid-template 定行列、fr/minmax 分弹性、grid-area 填内容,页面框架这件事从此有章法、可维护、好响应。

本文由作者按照 CC BY 4.0 进行授权