介绍一下 Grid 网格布局
问题解析
Grid 布局是 CSS 最强大的二维布局系统,能够同时处理行和列。面试考察这个问题,是想要了解候选人是否掌握现代 CSS 布局技术,以及能否利用 Grid 解决复杂布局问题。
什么是 Grid 布局
Grid 布局(网格布局) 是一个二维的布局方式,由纵横相交的两组网格线形成的框架性布局结构,能够同时处理行与列。
与 Flexbox(一维布局)的区别:
- Flexbox:单一方向,行或列
- Grid:两个方向,行和列
基础概念
网格线(Grid Lines)
划分网格的线,从 1 开始编号:
| | | | |
1 2 3 4 5 ← 列线
---------------------
| | | | | 1
---------------------
| | | | | 2
---------------------
| | | | | 3
---------------------
行线
网格轨道(Grid Tracks)
两条网格线之间的空间,即行或列。
网格单元(Grid Cell)
最小的单位,一个"格子"。
网格区域(Grid Area)
由多个网格单元组成的矩形区域。
容器属性
1. 定义 Grid
.container {
display: grid; /* 块级网格 */
display: inline-grid; /* 行内网格 */
}
2. 定义行列
.container {
/* 三列,固定宽度 */
grid-template-columns: 200px 200px 200px;
/* 两行,固定高度 */
grid-template-rows: 100px 200px;
/* 自动填充 */
grid-template-columns: repeat(3, 200px);
grid-template-rows: repeat(2, 100px);
/* 混合单位 */
grid-template-columns: 200px 1fr 2fr;
}
repeat() 函数
.container {
/* repeat(次数, 值) */
grid-template-columns: repeat(4, 1fr);
/* 自动填充 */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* 自动适应 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
minmax() 函数
.container {
/* 最小 200px,最大 1fr */
grid-template-columns: minmax(200px, 1fr) 1fr 1fr;
}
3. 网格间隙
.container {
/* 行列间隙相同 */
gap: 20px;
/* 分别设置 */
row-gap: 20px;
column-gap: 30px;
/* 旧语法(已废弃) */
grid-gap: 20px;
grid-row-gap: 20px;
grid-column-gap: 30px;
}
4. 定义网格区域
.container {
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
5. 网格流方向
.container {
grid-auto-flow: row; /* 默认,先行后列 */
grid-auto-flow: column; /* 先列后行 */
grid-auto-flow: row dense; /* 填充空白区域 */
}
6. 对齐方式
.container {
/* 单元格内容对齐 */
justify-items: start | end | center | stretch; /* 水平 */
align-items: start | end | center | stretch; /* 垂直 */
place-items: center; /* 简写 */
/* 整个内容区域对齐 */
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
place-content: center;
}
7. 隐式网格
当项目超出定义的网格时:
.container {
grid-auto-rows: 100px; /* 隐式行高 */
grid-auto-columns: 200px; /* 隐式列宽 */
}
项目属性
1. 网格线定位
.item {
/* 列线 2 到 4 */
grid-column-start: 2;
grid-column-end: 4;
/* 简写 */
grid-column: 2 / 4;
grid-column: 2 / span 2; /* 从 2 开始,跨 2 格 */
/* 行线 */
grid-row-start: 1;
grid-row-end: 3;
grid-row: 1 / 3;
/* 合并简写 */
grid-area: 1 / 2 / 3 / 4; /* 行开始 / 列开始 / 行结束 / 列结束 */
}
2. 命名区域定位
.item {
grid-area: header;
}
3. 单独对齐
.item {
justify-self: center; /* 水平居中 */
align-self: center; /* 垂直居中 */
place-self: center; /* 同时设置 */
}
实用布局示例
经典布局
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 60px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
gap: 20px;
}
.header { grid-area: header; background: #333; color: white; }
.sidebar { grid-area: sidebar; background: #f0f0f0; }
.main { grid-area: main; }
.footer { grid-area: footer; background: #333; color: white; }
响应式网格
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
/* 无需媒体查询,自动适应容器宽度 */
圣杯布局
.holy-grail {
display: grid;
grid-template-columns: 200px 1fr 200px;
gap: 20px;
}
@media (max-width: 768px) {
.holy-grail {
grid-template-columns: 1fr;
}
}
不规则布局
.masonry {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
gap: 10px;
}
.item-1 {
grid-column: span 2;
grid-row: span 2;
}
.item-2 {
grid-row: span 2;
}
Grid vs Flexbox
| 特性 | Flexbox | Grid |
|---|---|---|
| 维度 | 一维(行或列) | 二维(行和列) |
| 适用场景 | 组件内部布局、导航栏 | 页面整体布局、复杂网格 |
| 内容驱动 | 是(由内容决定尺寸) | 否(由网格决定尺寸) |
| 间隙 | gap(较新支持) | gap(原生支持) |
| 浏览器支持 | 很好 | 现代浏览器 |
协作使用:
.page {
display: grid; /* Grid 做整体布局 */
}
.card {
display: flex; /* Flexbox 做卡片内部布局 */
flex-direction: column;
}
高级特性
subgrid(子网格)
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.child {
display: grid;
grid-template-columns: subgrid; /* 继承父网格的列 */
}
网格命名线
.container {
grid-template-columns:
[sidebar-start] 200px
[sidebar-end main-start] 1fr
[main-end];
}
.item {
grid-column: sidebar-start / sidebar-end;
}
最佳实践
/* 1. 使用 fr 单位替代百分比 */
.container {
grid-template-columns: 1fr 2fr 1fr; /* 比例 1:2:1 */
}
/* 2. 响应式无需媒体查询 */
.responsive {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
/* 3. 使用 grid-area 提高可读性 */
.container {
grid-template-areas:
"header header"
"nav content"
"footer footer";
}
/* 4. 回退方案 */
.container {
display: flex;
flex-wrap: wrap;
}
@supports (display: grid) {
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
面试要点
- 能够说出 Grid 和 Flexbox 的主要区别
- 能够写出常用的网格布局代码
- 理解 fr 单位和 auto-fit/auto-fill 的区别
- 知道如何使用 grid-template-areas 定义布局
- 了解 Grid 的兼容性情况和回退方案
- 能够用 Grid 实现常见的两栏、三栏、网格布局