今天系统复习了 Grid 布局的核心概念,包括二维布局模型、轨道尺寸与 fr 单位、网格线定位、对齐方式、响应式网格以及 auto-fill 与 auto-fit 的区别。以下是当天的问答整理与知识总结。
一、Grid 基础概念与心智模型
1. Grid 与 Flexbox 的区别
| 特性 | Grid | Flexbox |
| 维度 | 二维(同时控制行和列) | 一维(主轴方向) |
| 布局思路 | 先定义网格结构,再放置项目 | 根据项目大小沿主轴排列 |
| 试用场景 | 整体页面布局、复杂网格、图片墙 | 导航栏、列表项、组件内对齐 |
|---|
2. 核心术语
- **容器:**设置 display: grid 的父元素。
- **项目:**容器的直接子元素。
- **行:**水平方向的轨道。
- **列:**垂直方向的轨道。
- **单元格:**行和列交叉形成的最小单位。
- **网格线:**分隔轨道的线,n 条轨道对应 n+1 条网格线。
二、轨道尺寸与 fr 单位
1. fr 单位
fr 表示剩余空间的一份比例,用于分配网格容器中未被固定宽度(或百分比)占用的空间。
css
.grid {
display: grid;
grid-template-columns: 200px 1fr 2fr;
}
- 第一列固定 200px。
- 剩余空间分为 3 份,第二列占 1 份,第三列占 2 份。
2. 与百分比、auto 的区别
| 单位 | 计算依据 | 特点 |
| fr | 剩余空间(扣除固定、百分比、内容后) | 灵活分配,不产生溢出 |
| 百分比 | 容器总宽度(包含固定宽度和间隙) | 可能因间隙导致溢出 |
| auto | 内容宽度 | 由内容撑开,不参与剩余空间分配 |
|---|
3. minmax() 函数
css
grid-template-columns: minmax(100px, 1fr) 2fr;
第一列最小 100px,最大占 1 份剩余空间;第二列固定占 2 份。常用于响应式,防止内容被压缩。
三、网格线定位、span 与网格命名
1. 基于网格线编号定位
网格线从 1 开始编号。grid-column 和 grid-row 可指定起始/结束线。
css
.item {
grid-column: 2 / 4; /* 从第2条列线到第4条列线 */
grid-row: 1 / 3; /* 从第1条行线到第3条行线 */
}
使用 span 关键字跨越指定数量:
css
.item {
grid-column: 2 / span 3; /* 从第2条线开始,跨越3列 */
}
2. grid-area 简写
顺序:row-start / column-start / row-end / column-end
css
.item {
grid-area: 2 / 3 / 4 / 5;
}
/* 等价于 */
grid-row-start: 2;
grid-column-start: 3;
grid-row-end: 4;
grid-column-end: 5;
3. 网格线命名
在定义轨道时给线起名:
css
.grid {
display: grid;
grid-template-columns: [main-start] 1fr [main-end] 1fr;
}
.item {
grid-column: main-start / main-end;
}
也可以使用 repeat 配合命名,如 repeat(3, [col] 1fr)。
四、对齐与间距控制
1. 项目对齐(*-items / *-self)
| 属性 | 作用 | 取值示例 |
| justify-items | 所有项目在行轴(水平)上的对齐 | start, end, center, stretch |
| align-items | 所有项目在列轴(垂直)上的对齐 | start, end, center, stretch |
| justify-self | 单个项目在行轴上的对齐 | 覆盖 justify-items |
| align-self | 单个项目在列轴上的对齐 | 覆盖 align-items |
|---|
2. 网格整体对齐(*-content)
当网格总尺寸小于容器时,控制整个网格区域的对齐。
- justify-content:水平方向
- align-content:垂直方向
取值:start, end, center, space-between, space-around, space-evenly
3. 与 Flexbox 对齐的对比
| 概念 | Grid | Flexbox |
| 单行项目对齐 | justify-items / align-items | justify-content / align-items(注意:Flex 中 justify-content 控制主轴,align-items 控制交叉轴) |
| 整体对齐 | justify-content / align-content | 只有单行时 align-content 无效(需 flex-wrap: wrap 且多行) |
| 单个项目覆盖 | justify-self / align-self | align-self(无 justify-self,可用 margin: auto 替代) |
|---|
4. 间距 gap
css
.grid {
gap: 16px; /* 行和列间距均为16px */
gap: 16px 24px; /* 行间距16px,列间距24px */
}
- gap 只控制项目之间的间距,不会导致父容器塌陷,比 margin 更简洁。
- 边缘间距需要用父容器的 padding 实现。
五、响应式网格与自动布局
1. 自动填充 repeat(auto-fill, minmax(200px, 1fr))
css
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
- 浏览器根据容器宽度自动计算能容纳多少列,每列最小 200px,最大占 1fr。
- 当宽度不足时,列数减少,每列自动拉伸。
2. auto-fill vs auto-fit
| 关键字 | 行为 | 视觉效果 |
| auto-fill | 尽可能多地填充轨道,即使没有项目也会保留空轨道 | 右侧可能留白 |
| auto-fit | 填充轨道后,拉伸已有项目填满容器 | 无留白,项目更宽 |
|---|
**示例:**容器宽度 600px,minmax(200px, 1fr),最多能放 3 列。
只有 2 个项目时:
- auto-fill:仍然保留 3 个轨道位置,第 3 个轨道空白。
- auto-fit:只有 2 个轨道,每个占 300px。
3. 媒体查询适配
css
/* 移动端:希望项目尽量宽,不留白 */
.grid {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
/* 桌面端:希望保留空白或固定列数 */
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
4. display: grid 与 inline-grid
- display: grid:块级网格容器,独占一行。
- display: inline-grid:行内网格容器,宽度由内容或 grid-template-columns 决定。
今日知识点总结
| 概念 | 要点 |
| 二维布局 | 先定义网格结构,再放置项目;适合整体页面、复杂网格 |
| fr 单位 | 剩余空间的一份比例,与百分比、auto 的区别 |
| minmax( ) | 定义轨道的最小/最大尺寸,响应式核心 |
| 网格线定位 | 基于编号或命名,使用 span 跨越;grid-area 简写 |
| 对齐方式 | *-items(单元格内对齐)、*-content(网格整体对齐)、*-self(单个项目覆盖) |
| 间距 gap | 仅控制项目间间距,边缘用 padding |
| 响应式 | repeat(auto-fill/auto-fit, minmax(min, max)) 实现弹性网格 |
| auto-fill vs auto-fit | auto-fill 保留空轨道,auto-fit 拉伸项目填满 |
|---|
常见追问
1. 如何实现一个不等高卡片网格?
Grid 默认每行高度由该行最高卡片决定,无需特殊处理。若想实现瀑布流(各卡片高度独立),原生 Grid 不支持,可用 column-count 或 Masonry 库。
2. grid-template-areas 的作用?
通过命名区域直观定义布局,适合固定模板的页面(如 header、main、sidebar、footer)。
css
.container {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
3. 如何让某个子项跨越所有列?
grid-column: 1 / -1;(-1 表示最后一条网格线)。
4. minmax(100px, max-content) 与 minmax(100px, auto) 的区别?
max-content 取内容的最大宽度(不换行),auto 受 min-width / max-width 影响,通常更常用 auto。