一、Grid 是什么,为什么需要它
CSS Grid(网格布局)是 CSS 中最强大的二维布局系统。它可以将页面划分为行和列组成的网格,精确控制元素在网格中的位置和尺寸。
一维 vs 二维布局
Flexbox 是一维布局——只能在行或列方向上排列元素。Grid 是二维布局——可以同时控制行和列。
1 2 3 4 5 6 7 8 9 10
| Flexbox 一维: Grid 二维: ┌────┬────┬────┐ ┌────┬────┬────┐ │ │ │ │ │ │ │ │ │ 一 │ 行 │ 排 │ │ │ 二 │ │ │ │ │ │ │ │ 维 │ │ ├────┼────┼────┤ ├────┼────┼────┤ │ │ │ │ │ │ 排 │ │ │ 只 │ 能 │ 操 │ │ │ 列 │ │ │ │ │ │ │ │ 兼 │ │ └────┴────┴────┘ └────┴────┴────┘
|
Grid vs Flexbox 选型
| 场景 | 推荐方案 |
|---|
| 页面整体骨架(header/sidebar/main/footer) | Grid |
| 卡片网格、图片画廊 | Grid |
| 导航栏、按钮组、表单行 | Flexbox |
| 一列居中 + 另一列自适应 | Flexbox |
| 不知元素数量,需要自动折行 | Grid(auto-fill)或 Flexbox(flex-wrap) |
二、基础概念
Grid 容器(Container)
设置了 display: grid 的元素成为网格容器,其直接子元素自动成为网格项。
1 2 3 4 5
| .container { display: grid; display: inline-grid; }
|
网格线(Grid Line)
划分网格的线,编号从 1 开始。可以给网格线命名。
网格轨道(Grid Track)
两条相邻网格线之间的区域——即一行或一列。
网格单元(Grid Cell)
四条网格线围成的最小区域。
网格区域(Grid Area)
任意多个网格单元组成的矩形区域。
1 2 3 4 5 6 7 8 9 10
| │ 列线1 │ 列线2 │ 列线3 │ 列线4 ──┼───────┼───────┼───────┼──── 行线1 │ │ │ │ │ │ 单元 │ │ 行线2 │ │ │ │ │ ├───────┤ │ 行线3 │ │ 区域 │ │ │ │ │ │ 行线4 │ │ │ │ ──┼───────┴───────┴───────┴────
|
三、定义网格
grid-template-columns / grid-template-rows
1 2 3 4 5 6
| .container { display: grid; grid-template-columns: 100px 200px 1fr; grid-template-rows: 100px auto 100px; gap: 16px; }
|
fr 单位
fr 代表剩余空间的分数(fraction),是 Grid 中最常用的自适应单位:
1 2 3 4 5 6 7 8 9
| grid-template-columns: 1fr 1fr 1fr;
grid-template-columns: 240px 1fr;
grid-template-columns: 100px 1fr 2fr;
|
repeat() 函数
1 2 3 4 5 6 7 8 9
| grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(4, 100px 1fr);
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
minmax() 函数
1 2 3 4 5
| grid-template-columns: repeat(3, minmax(200px, 1fr));
grid-template-columns: minmax(200px, 400px) 1fr;
|
auto-fill vs auto-fit
1 2 3 4 5
| grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
区别在于:当元素不足时,auto-fill 会留下空白轨道,auto-fit 会将空轨道折叠,让已有元素拉伸填充。
网格间距 gap
1 2 3 4 5
| .container { gap: 16px 24px; row-gap: 16px; column-gap: 24px; }
|
四、放置网格项
1. 自动放置(默认)
子元素按顺序自动填充网格,从左到右、从上到下:
1 2 3 4 5
| .container { display: grid; grid-template-columns: repeat(3, 1fr); }
|
2. 基于网格线的放置
使用 grid-row 和 grid-column 指定起止网格线编号:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| .item { grid-column: 1 / 3; grid-row: 1 / 3; }
.item { grid-column: 1 / span 2; grid-row: 1 / span 2; }
.item { grid-column: 2 / -1; }
|
3. 基于网格区域的放置
使用 grid-template-areas 定义命名区域,子元素通过 grid-area 指定归属:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| .layout { display: grid; grid-template-columns: 200px 1fr 200px; grid-template-rows: auto 1fr auto; grid-template-areas: "header header header" "sidebar main aside" "footer footer footer"; min-height: 100vh; }
.header { grid-area: header; } .sidebar { grid-area: sidebar; } .main { grid-area: main; } .aside { grid-area: aside; } .footer { grid-area: footer; }
|
命名区域的规则:
- 每个单元格用名称标记,空格分隔
- 同一区域必须是矩形(不能是 L 形)
- 用
. 表示空单元格
1 2 3 4
| grid-template-areas: "header header header" "sidebar . aside" /* 中间列跳过 */ "footer footer footer";
|
五、对齐
Grid 提供两层对齐控制:容器级别和项目级别。
容器级别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .container { display: grid; grid-template-columns: 100px 100px; grid-template-rows: 100px 100px;
justify-content: center;
align-content: center;
justify-items: stretch;
align-items: stretch; }
|
项目级别
1 2 3 4 5
| .item { justify-self: center; align-self: end; }
|
六、隐式网格
当项目放置在已定义的行列之外时,Grid 会自动生成隐式网格轨道。
1 2 3 4 5 6 7 8
| .container { grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, 100px); }
.item:nth-child(10) { grid-column: 4; }
|
控制隐式轨道的大小:
1 2 3 4 5 6 7 8 9
| .container { grid-auto-rows: 100px; grid-auto-columns: 1fr; grid-auto-flow: row; grid-auto-flow: row dense; }
|
七、响应式布局模式
模式一:自动折行网格
1 2 3 4 5
| .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
|
效果:每列最小 280px,容器宽时列数增加,窄时列数减少,无需媒体查询。
模式二:断点切换
1 2 3 4 5 6 7 8 9 10 11 12 13
| .grid { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 640px) { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(3, 1fr); } }
|
模式三:经典圣杯布局
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .layout { display: grid; grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; min-height: 100vh; }
@media (min-width: 768px) { .layout { grid-template-columns: 200px 1fr 200px; grid-template-rows: auto 1fr auto; grid-template-areas: "header header header" "sidebar main aside" "footer footer footer"; } }
|
模式四:Dashboard 面板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .dashboard { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.dashboard .full-width { grid-column: 1 / -1; }
.dashboard .double { grid-column: span 2; }
.dashboard .tall { grid-row: span 2; }
|
八、Grid 与 Flexbox 组合使用
Grid 负责页面级宏观布局,Flexbox 负责组件级微观排列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| .page { display: grid; grid-template-columns: 250px 1fr; grid-template-rows: 60px 1fr; grid-template-areas: "header header" "sidebar main"; }
.toolbar { display: flex; justify-content: space-between; align-items: center; }
.card-footer { display: flex; gap: 8px; justify-content: flex-end; }
|
九、Grid 调试
Chrome DevTools 提供了强大的 Grid 调试功能:
- 选中设置了
display: grid 的元素 - DevTools 的 Elements 面板中会出现
grid 徽章 - 点击徽章可以高亮显示网格线、显示网格编号、查看网格轨道大小
十、常见问题
Q1: 老旧浏览器的兼容性
CSS Grid 在 Chrome 57+、Firefox 52+、Safari 10.1+、Edge 16+ 中得到支持。如需兼容 IE,可以使用 Autoprefixer 添加 -ms- 前缀,但 IE 仅支持旧版 Grid 规范,功能受限。
Q2: gap 在 Flexbox 中能用吗
1 2 3 4 5
| .flex-container { display: flex; gap: 16px; }
|
Q3: 内容超出网格怎么办
1 2 3 4 5
| .item { overflow: auto; word-break: break-all; }
|
十一、推荐学习路径
- 理解 Grid 的二维本质和核心概念(容器、项目、网格线、轨道)
- 掌握
grid-template-columns 和 repeat()/minmax()/fr - 练习网格放置:
grid-column、grid-row、grid-area - 用
grid-template-areas 搭建页面骨架 - 结合
auto-fill/auto-fit 和 minmax 做响应式布局 - 与 Flexbox 组合使用:Grid 管宏观、Flexbox 管微观