Grid 布局
面试速答(30 秒版 TL;DR)
- Grid(CSS Grid Layout)是 二维布局系统:可以同时控制列(column)和行(row);Flex 更偏 一维布局。
- 最稳的答法是 4 句话:
- 容器先定义 轨道(tracks):
grid-template-columns、grid-template-rows - 子项再决定 放在哪些格子:
grid-column、grid-row、grid-area - 空间不够时会生成 隐式网格(implicit grid):
grid-auto-* - 对齐分两层:单元格内对齐 用
justify-items/align-items,整个轨道组在容器内对齐 用justify-content/align-content
- 容器先定义 轨道(tracks):
- Grid 高频函数/关键字:
repeat()、minmax()、fit-content()fr、auto-fill、auto-fit、span- 命名网格线
[name]、命名区域grid-template-areas
- 工程高频场景:后台骨架、圣杯布局、卡片墙、看板、相册矩阵、响应式网格。
心智模型
把 Grid 想成:
先画棋盘,再决定每个元素占哪几格;最后再决定格子里的元素怎么对齐。
所以 Grid 的题,永远按这条线回答最稳:
- 网格怎么画:几列几行,显式还是隐式。
- 元素怎么放:从哪条线开始,到哪条线结束,是否跨行跨列。
- 剩余空间怎么分:
fr、minmax()、auto-fit/auto-fill。 - 元素怎么对齐:单元格内对齐 vs 整体轨道对齐。
一、先把 6 个基础概念说清楚
1)网格容器(grid container)和网格项(grid item)
- 父元素设置
display: grid或display: inline-grid后,就是网格容器 - 直接子元素就是网格项
.layout {
display: grid; /* 块级 grid 容器 */
}
.inlineLayout {
display: inline-grid; /* 容器本身按行内级盒子参与外部排版 */
}
2)轨道(track)
- 一列就是一个列轨道(column track)
- 一行就是一个行轨道(row track)
3)网格线(grid line)
- 每条轨道边界都是一条线
grid-column: 2 / 4的意思,不是“第 2 列到第 4 列”,而是“从第 2 条列线到第 4 条列线”
4)单元格(cell)
- 行和列交叉形成的最小格子
5)区域(area)
- 多个相邻单元格组成一个网格区域
grid-area既可以引用命名区域,也可以直接写起止线的简写
6)显式网格(explicit grid)和隐式网格(implicit grid)
- 你手动写出来的
grid-template-columns、grid-template-rows属于显式网格 - 项目放不下、或者你把子项放到显式网格之外时,浏览器会自动补出隐式网格
- 隐式网格的尺寸由
grid-auto-columns、grid-auto-rows控制
二、容器属性(Container)完整清单
这一部分最容易答散。建议按“画网格 -> 补隐式网格 -> 做间距 -> 做对齐 -> 简写”来讲。
1)开启 Grid:display
.grid {
display: grid;
}
.inlineGrid {
display: inline-grid;
}
grid:容器本身是块级盒子inline-grid:容器本身是行内级盒子,但内部子项仍按 Grid 算法布局
2)定义显式列轨道:grid-template-columns
.cards {
display: grid;
grid-template-columns: 240px 1fr 2fr;
}
含义:
- 第 1 列固定
240px - 后两列按剩余空间按
1:2分配
常见值:
- 固定长度:
200px - 百分比:
25% - 内容尺寸:
auto、max-content、min-content - 剩余空间份额:
fr - 函数:
repeat()、minmax()、fit-content() - Level 2 常见值:
subgrid
3)定义显式行轨道:grid-template-rows
.page {
display: grid;
grid-template-rows: 64px 1fr auto;
}
这个写法很适合页面骨架:
- 第一行头部固定高
- 第二行主内容吃剩余空间
- 第三行底部高度由内容决定
4)命名区域:grid-template-areas
.dashboard {
display: grid;
grid-template-columns: 220px minmax(0, 1fr);
grid-template-rows: 64px 1fr;
grid-template-areas:
"header header"
"sidebar main";
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.main {
grid-area: main;
min-width: 0;
}
规则要点:
- 每一行字符串的列数必须一致
.表示空白单元格- 同名区域必须组成一个 矩形
- 这个属性表达力很强,特别适合页面骨架题
5)grid-template 简写
它是下面 3 个属性的简写:
grid-template-rowsgrid-template-columnsgrid-template-areas
示例:
.layout {
display: grid;
grid-template:
"header header" 64px
"sidebar main" 1fr
/ 220px minmax(0, 1fr);
}
面试里知道它是简写即可,工程里拆开写通常更清楚。
6)隐式列轨道尺寸:grid-auto-columns
.gallery {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-columns: 120px;
}
当你把某个元素放到显式列以外时,新补出来的隐式列宽度由它决定。
7)隐式行轨道尺寸:grid-auto-rows
.list {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(80px, auto);
}
这是很高频的写法:自动生成的新行至少 80px 高,内容多时可以继续撑开。
8)自动放置规则:grid-auto-flow
.autoFlow {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-flow: row;
}
常见值:
row:默认值,先按行填,放满一行再去下一行column:按列填row densecolumn dense
dense 的含义:
- 浏览器会尝试把后面的较小项目回填到前面留下的空洞
- 结果是视觉上更“紧凑”,但视觉顺序可能和 DOM 顺序不完全一致
9)间距:gap、row-gap、column-gap
.cards {
display: grid;
gap: 16px 24px;
}
含义:
- 行间距
16px - 列间距
24px
优先级建议:
- 新代码优先
gap row-gap/column-gap在需要单独控制时再拆开- 老写法
grid-gap属于历史兼容写法,面试知道即可,不建议当首选答案
10)单元格内对齐:justify-items、align-items、place-items
这组属性控制的是:
网格项在自己的单元格/区域内部怎么摆
.board {
display: grid;
grid-template-columns: repeat(3, 120px);
justify-items: center;
align-items: center;
}
justify-items:行内轴(inline axis) 对齐,默认通常可理解为横向align-items:块轴(block axis) 对齐,默认通常可理解为纵向place-items:align-items / justify-items的简写
常见值:
stretch(默认)startendcenter
11)整个轨道组对齐:justify-content、align-content、place-content
这组属性控制的是:
整个网格轨道组在容器里怎么摆
只有当“网格总尺寸小于容器尺寸”时,这组属性效果才明显。
.panel {
display: grid;
width: 800px;
height: 500px;
grid-template-columns: repeat(2, 200px);
grid-template-rows: repeat(2, 100px);
justify-content: center;
align-content: space-between;
}
justify-content:控制整组轨道在行内轴上的分布align-content:控制整组轨道在块轴上的分布place-content:align-content / justify-content的简写
常见值:
startendcenterstretchspace-betweenspace-aroundspace-evenly
12)grid 总简写
grid 是 Grid 的总简写,能同时覆盖:
grid-template-*grid-auto-*grid-auto-flow
面试知道它存在即可。工程里如果不是特别熟,拆开写更稳,因为 grid 可读性一般,写错也不容易排查。
三、子项属性(Item)完整清单
Grid 子项的核心问题只有一个:
它从哪条线开始,到哪条线结束;如果不显式指定,就按自动放置规则进入网格。
1)grid-column-start
.cardA {
grid-column-start: 2;
}
表示从第 2 条列线开始。
它可以写:
- 数字:
2 - 负数:
-1表示最后一条线 - 命名线:
content-start - 关键字:
auto - 跨度:
span 2
2)grid-column-end
.cardA {
grid-column-start: 2;
grid-column-end: 4;
}
表示排到第 4 条列线结束。
3)grid-row-start
.cardB {
grid-row-start: 1;
}
4)grid-row-end
.cardB {
grid-row-start: 1;
grid-row-end: 3;
}
5)grid-column 简写
.main {
grid-column: 2 / 4;
}
等价于:
.main {
grid-column-start: 2;
grid-column-end: 4;
}
高频写法:
.header {
grid-column: 1 / -1;
}
.wideCard {
grid-column: span 2;
}
1 / -1:从第一条线铺到最后一条线,常用于整行占满span 2:横向跨 2 列
6)grid-row 简写
.sidebar {
grid-row: 1 / 3;
}
表示跨两行。
7)grid-area
grid-area 有两种用法。
第一种:引用命名区域。
.main {
grid-area: main;
}
第二种:四值简写。
.hero {
grid-area: 1 / 1 / 3 / 3;
}
它等价于:
grid-row-start: 1grid-column-start: 1grid-row-end: 3grid-column-end: 3
面试里如果被追问,直接回答:
grid-area既能写命名区域,也能写row-start / column-start / row-end / column-end的四值简写。
8)子项自对齐:justify-self、align-self、place-self
这组属性用于覆盖容器上的 justify-items / align-items,只对单个子项生效。
.badge {
justify-self: end;
align-self: start;
}
justify-self:单个项目在行内轴上的对齐align-self:单个项目在块轴上的对齐place-self:align-self / justify-self简写
9)order
Grid item 也支持 order。
.promo {
order: -1;
}
作用:
- 影响自动放置时的视觉顺序
- 不改变 DOM 顺序
- 无障碍、键盘导航、读屏语义不应该只靠它解决
四、Grid 里常用的单位、函数、关键字
这部分是面试高频,也是工程里最容易写错的地方。
1)fr
fr(fraction)表示 剩余空间的份额。
grid-template-columns: 1fr 2fr;
含义:
- 剩余空间按
1:2分给两列
注意:
fr分的是 剩余空间- 先扣掉固定宽度、内容约束、
gap等,再分配给fr
2)repeat()
减少重复书写。
grid-template-columns: repeat(3, 1fr);
等价于:
grid-template-columns: 1fr 1fr 1fr;
还能配合自动轨道生成:
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
3)minmax(min, max)
给轨道设置上下界。
grid-template-columns: minmax(200px, 1fr) 2fr;
含义:
- 第一列最小
200px - 空间足够时最多按
1fr参与剩余空间分配
工程高频:
grid-template-columns: repeat(3, minmax(0, 1fr));
为什么常写 minmax(0, 1fr) 而不是直接 1fr?
- 因为 Grid item 可能受默认最小内容尺寸影响,不愿继续收缩
minmax(0, 1fr)可以更明确地告诉浏览器:这列允许缩到0- 如果内容仍然溢出,再配合子项
min-width: 0更稳
4)fit-content()
表示:
轨道可以随内容增长,但不要超过给定上限。
grid-template-columns: 200px fit-content(320px) 1fr;
适合场景:
- 某一列想“内容驱动”,但又不想无限变宽
- 比如标签列、时间列、操作列
5)auto-fill 和 auto-fit
这两个常和 repeat() + minmax() 一起用,做响应式卡片墙。
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
区别:
auto-fill:尽量 保留轨道槽位auto-fit:尽量 折叠空轨道,让已有项目撑开
面试标准答法:
- 两者都会自动生成尽可能多的轨道
auto-fill更像“先把坑位占好”auto-fit更像“空坑位可以折叠,空间让给已有元素”
6)span
表示跨越多少个轨道。
.feature {
grid-column: span 2;
grid-row: span 2;
}
这比手写结束线在很多场景更直观。
7)命名网格线:[line-name]
.layout {
display: grid;
grid-template-columns:
[sidebar-start] 220px
[sidebar-end content-start] minmax(0, 1fr)
[content-end];
}
.main {
grid-column: content-start / content-end;
}
优点:
- 语义比纯数字强
- 大型布局比数线更不容易写错
8)subgrid
subgrid 是 Grid Level 2 的重要能力,常见于:
.itemList {
display: grid;
grid-template-columns: subgrid;
}
含义:
- 子网格直接继承父网格对应轴的轨道定义
- 适合需要和父布局严格对齐的复杂组件
面试里知道它的价值即可:
- 父子网格对齐更自然
- 不用重复维护相同的轨道尺寸
如果团队需要兼容较老浏览器,落地前仍要确认实际兼容范围。
9)非 Grid 专属,但经常一起出现的函数
这些不是 Grid 独有,但经常配合 Grid 使用:
min()max()clamp()
比如:
grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
这种写法常用于小屏防止卡片最小宽度把容器撑爆。
五、面试里怎么系统地讲“所有属性”
如果面试官问“Grid 有哪些属性”,不要背流水账。推荐按下面这套答:
1)容器属性
- 建显式网格:
grid-template-columnsgrid-template-rowsgrid-template-areasgrid-template
- 控制隐式网格:
grid-auto-columnsgrid-auto-rowsgrid-auto-flow
- 间距:
gaprow-gapcolumn-gap
- 单元格内对齐:
justify-itemsalign-itemsplace-items
- 整组轨道对齐:
justify-contentalign-contentplace-content
- 总简写:
grid
2)子项属性
- 放置位置:
grid-column-startgrid-column-endgrid-row-startgrid-row-endgrid-columngrid-rowgrid-area
- 单项对齐:
justify-selfalign-selfplace-self
- 排序:
order
3)常用函数和值
frrepeat()minmax()fit-content()auto-fillauto-fitspan[line-name]subgrid
六、典型场景(最小可用代码)
1)后台骨架布局
<div class="admin">
<header class="admin__header">header</header>
<aside class="admin__sidebar">sidebar</aside>
<main class="admin__main">main</main>
</div>
.admin {
display: grid;
min-height: 100vh;
grid-template-columns: 220px minmax(0, 1fr);
grid-template-rows: 64px 1fr;
grid-template-areas:
"header header"
"sidebar main";
}
.admin__header {
grid-area: header;
}
.admin__sidebar {
grid-area: sidebar;
}
.admin__main {
grid-area: main;
min-width: 0;
}
2)响应式卡片墙
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
这是 Grid 最常见的工程写法之一。
3)局部元素跨列
.news {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.news > .hero {
grid-column: 1 / -1;
}
hero 会整行占满,其余卡片按正常网格排。
4)回填空洞的卡片布局
.masonryLike {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 80px;
grid-auto-flow: row dense;
gap: 12px;
}
.masonryLike > .tall {
grid-row: span 2;
}
注意:
- 这是“类瀑布流”思路,不是真正意义上的 masonry
dense可能改变视觉填充顺序,面试时可以顺手提这个坑
七、典型题 & 标准答法
Q1:Grid 和 Flex 有什么本质区别?
答:
- Flex 更适合一维布局,主要解决一行或一列里的分配与对齐
- Grid 更适合二维布局,可以同时定义行和列
- 工程里常见搭配是:页面骨架用 Grid,局部组件内部对齐用 Flex
Q2:justify-items 和 justify-content 有什么区别?
答:
justify-items控制的是 每个 grid item 在自己格子里怎么摆justify-content控制的是 整组网格轨道在容器里怎么摆- 一个是“格子内部对齐”,一个是“整张网格对齐”
Q3:auto-fit 和 auto-fill 的区别?
答:
- 两者都常用于
repeat(..., minmax(...)) auto-fill更倾向保留空轨道auto-fit更倾向折叠空轨道,让已有项目撑开
Q4:为什么 1fr 有时会撑爆,工程里常写 minmax(0, 1fr)?
答:
- 因为 Grid item 默认会受最小内容尺寸约束
- 直接写
1fr时,某些长内容可能让轨道不愿继续缩 minmax(0, 1fr)是在明确告诉浏览器:这列最小可以缩到0- 真实项目里再配合子项
min-width: 0更稳
Q5:grid-area 和 grid-template-areas 是什么关系?
答:
grid-template-areas是容器定义命名区域grid-area是子项把自己放进某个命名区域- 但
grid-area也可以单独写四值简写,不一定非要配合命名区域
Q6:Grid 项会自动换行吗?
答:
- 会,但更准确的说法不是“换行”,而是 按自动放置规则流入下一条隐式轨道
- 如果你定义了多列,后续项目默认会继续排到下一行
Q7:什么时候不用 Grid?
答:
- 当问题本质只是单行分布、单列对齐、按钮组、导航、简单居中时,Flex 更直接
- Grid 的优势在二维结构,不要为了“高级”而强行上 Grid
八、常见追问
1)命名区域和数字线编号,哪个更好?
- 页面骨架、语义化布局:
grid-template-areas更直观 - 复杂卡片拼排、跨列跨行:数字线 / 命名线更灵活
- 大型工程里,两者可以混用
2)dense 值要不要常用?
- 不建议默认就用
- 它适合“视觉紧凑优先”的卡片流
- 如果页面很依赖视觉顺序和 DOM 顺序一致,就要谨慎
3)subgrid 解决什么问题?
- 解决父子网格轨道难对齐的问题
- 让子组件能继承父组件的网格轨道
- 适合复杂表单、卡片列表、信息面板
4)Grid 能完全替代圣杯布局、双飞翼布局吗?
- 在现代工程里,大多数情况下可以直接替代
- 但面试仍然会问圣杯/双飞翼,是为了考你对历史布局方案的理解
九、易错点 / 坑
- 把
grid-column: 2 / 4理解成“第 2 列到第 4 列”,其实它说的是 第 2 条线到第 4 条线。 - 把
justify-items和justify-content混为一谈:一个管 项目在格子里,一个管 整张网格在容器里。 - 只会背
auto-fit/auto-fill结论,不知道它们都是在repeat()里自动生成轨道。 - 以为 Grid 的“自动换行”和 Flex 的
wrap完全一样;更准确说法是 自动放置到后续隐式轨道。 - 直接写
1fr,结果长内容撑爆布局;常见修复是minmax(0, 1fr)或子项min-width: 0。 - 乱用
order或dense改视觉顺序,却忽略 DOM 顺序、读屏顺序和键盘导航顺序。 - 区域名拼错、
grid-template-areas每行列数不一致、同名区域不是矩形,都会导致布局异常。
十、速记要点(可背诵)
- Grid 是二维,Flex 是一维。
- Grid 解题顺序:先画网格,再放元素,再谈对齐。
- 容器高频:
grid-template-*、grid-auto-*、gap、justify/align/place-*。 - 子项高频:
grid-column、grid-row、grid-area、justify/align/place-self。 - 高频函数:
repeat()、minmax()、fit-content()。 - 高频值:
fr、auto-fit、auto-fill、span、subgrid。 - 整行铺满常写:
grid-column: 1 / -1。 - 工程里最常见的一句:
repeat(auto-fit, minmax(240px, 1fr))。