CSS Grid 网格布局从入门到实战 2026 | 零基础入门教程

学会了 Flexbox 之后,你可能会遇到更复杂的布局需求:比如把页面分成「头部、侧边、内容、底部」四个区域,或者做一个相册网格。这时候 CSS Grid 就登场了!Grid 是比 Flexbox 更强大的二维布局系统,这篇教程继续用大白话带你从零掌握。
一、Grid 和 Flexbox 有什么区别?
1.1 通俗对比
| 特性 | Flexbox | Grid |
|---|---|---|
| 维度 | 一维(一行或一列) | 二维(行和列同时) |
| 比喻 | 排队 | 桌子摆盘子 |
| 适用场景 | 导航栏、按钮组、居中 | 整页布局、相册、表格 |
| 控制方式 | 从内容出发 | 从容器出发 |
大白话理解:
- Flexbox 就像排队——大家排成一行(或一列),重点是「排队的方向」
- Grid 就像在桌子上摆盘子——先画好格子,再把盘子放到指定的格子里
1.2 什么时候用 Grid?
| 场景 | 例子 |
|---|---|
| 整页布局 | 头部 + 侧边栏 + 内容 + 底部 |
| 图片相册 | 3×3 的照片网格 |
| 表单布局 | 标签和输入框对齐 |
| 卡片网格 | 商品列表、文章列表 |
| 仪表盘 | 多个面板的复杂排列 |
1.3 最简单的例子
<div class="grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>.grid {
display: grid;
grid-template-columns: 100px 100px 100px; /* 3列,每列100px */
grid-template-rows: 80px 80px; /* 2行,每行80px */
gap: 10px; /* 间距10px */
}
.item {
background: #4a90d9;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}效果: 6 个方块自动排成了 3 列 2 行的网格,整齐又美观!
┌───────┬───────┬───────┐
│ 1 │ 2 │ 3 │
├───────┼───────┼───────┤
│ 4 │ 5 │ 6 │
└───────┴───────┴───────┘二、定义网格:行和列
2.1 grid-template-columns(定义列)
这是 Grid 中最重要的属性,用来定义有多少列、每列多宽:
.grid {
display: grid;
/* 3列,每列100px */
grid-template-columns: 100px 100px 100px;
/* 2列,第一列200px,第二列300px */
grid-template-columns: 200px 300px;
/* 3列,每列相等(auto表示均分) */
grid-template-columns: auto auto auto;
}2.2 fr 单位(重点!)
fr 是 Grid 特有的单位,表示「按比例分配剩余空间」,就像 Flexbox 的 flex-grow:
.grid {
display: grid;
/* 3列等宽 */
grid-template-columns: 1fr 1fr 1fr;
/* 等价于 */
grid-template-columns: repeat(3, 1fr);
/* 第一列固定200px,剩余空间按1:2分配 */
grid-template-columns: 200px 1fr 2fr;
/* 第一列按内容撑开,第二列占1份,第三列占2份 */
grid-template-columns: auto 1fr 2fr;
}💡 大白话:
fr就是「份」。1fr 2fr就是按 1:2 的比例分蛋糕。
2.3 repeat() 函数
当列数很多时,用 repeat() 更简洁:
.grid {
display: grid;
/* 重复3次 1fr,等价于 1fr 1fr 1fr */
grid-template-columns: repeat(3, 1fr);
/* 重复4次 100px */
grid-template-columns: repeat(4, 100px);
/* 混合使用 */
grid-template-columns: 200px repeat(3, 1fr) 100px;
}2.4 auto-fit 和 auto-fill(自动列数)
这两个值可以实现「自动响应式」,不需要写媒体查询!
.grid {
display: grid;
/* 自动适应:每列最少200px,放不下就换行 */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}这是 Grid 最强大的功能之一! 上面的代码会:
- 屏幕宽时,自动多放几列
- 屏幕窄时,自动减少列数
- 每列最少 200px,剩余空间均分
auto-fit 和 auto-fill 的区别:
auto-fit:空的格子会塌缩,让现有格子撑满auto-fill:保留空格子位置
💡 99% 的情况下用
auto-fit就对了!
2.5 grid-template-rows(定义行)
和 grid-template-columns 类似,用来定义行的高度:
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
/* 3行,第一行100px,第二行200px,第三行100px */
grid-template-rows: 100px 200px 100px;
/* 第一行按内容,第二行占满剩余 */
grid-template-rows: auto 1fr;
}💡 大多数情况下,行高不需要手动定义,让内容自动撑开就好。
2.6 gap(间距)
和 Flexbox 一样,Grid 也可以用 gap 设置间距:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px; /* 行列间距都是16px */
/* 或者分别设置 */
row-gap: 20px; /* 行间距 */
column-gap: 16px; /* 列间距 */
}三、网格线(Grid Lines)
3.1 什么是网格线?
Grid 会自动给每条线编号,从 1 开始:
1 2 3 4
│ │ │ │
1 ├───────┼───────┼───────┤
│ 1 │ 2 │ 3 │
2 ├───────┼───────┼───────┤
│ 4 │ 5 │ 6 │
3 └───────┴───────┴───────┘- 列线:1, 2, 3, 4(从左到右)
- 行线:1, 2, 3(从上到下)
3.2 用网格线定位子元素
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 100px 100px;
}
/* 把 A 放到第2列到第3列,第1行到第2行 */
.item-a {
grid-column: 2 / 3; /* 从第2条线到第3条线 */
grid-row: 1 / 2; /* 从第1条线到第2条线 */
}
/* 把 B 放到第1列到第3列(跨2列),第2行到第3行 */
.item-b {
grid-column: 1 / 3; /* 跨2列 */
grid-row: 2 / 3;
}💡 大白话:
grid-column: 2 / 4意思是「从第 2 条线开始,到第 4 条线结束」,也就是占了第 2 和第 3 两列。
3.3 跨越的简写
/* 从第1列开始,跨3列 */
.item {
grid-column: 1 / span 3;
/* 等价于 */
grid-column: 1 / 4;
}
/* 从当前位置开始,跨2列 */
.item {
grid-column: span 2;
}💡 记忆技巧:
span N就是「跨越 N 个格子」。
四、网格区域(Grid Areas)
4.1 给区域命名
可以用名字来命名网格区域,非常直观:
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}就像画了一个表格:
┌──────────────────────────┐
│ header │
├──────────┬───────────────┤
│ sidebar │ content │
├──────────┴───────────────┤
│ footer │
└──────────────────────────┘4.2 使用命名区域
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
.footer {
grid-area: footer;
}💡 这是 Grid 最直观的用法! 画个「ASCII 图」就能定义布局,一目了然。
4.3 用点号表示空区域
.grid {
grid-template-areas:
"header header header"
"sidebar . content"
"footer footer footer";
}中间的 . 表示这个位置留空。
4.4 响应式布局(改变区域排列)
.layout {
display: grid;
grid-template-columns: 1fr;
grid-template-areas:
"header"
"content"
"sidebar"
"footer";
}
/* 大屏幕改成左右布局 */
@media (min-width: 768px) {
.layout {
grid-template-columns: 200px 1fr;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
}💡 超方便! 只需要改
grid-template-areas就能切换布局,HTML 完全不用动!
五、对齐方式
5.1 容器对齐(整体)
| 属性 | 作用 | 类比 Flexbox |
|---|---|---|
justify-items | 子元素在格子内的水平对齐 | 无直接对应 |
align-items | 子元素在格子内的垂直对齐 | align-items |
justify-content | 整个网格在容器内的水平位置 | justify-content |
align-content | 整个网格在容器内的垂直位置 | align-content |
.grid {
display: grid;
grid-template-columns: repeat(3, 100px);
height: 400px;
/* 每个格子内的子元素:水平居中 */
justify-items: center;
/* 每个格子内的子元素:垂直居中 */
align-items: center;
/* 整个网格水平居中 */
justify-content: center;
/* 整个网格垂直居中 */
align-content: center;
}5.2 子元素对齐(单独)
.item {
/* 单独设置这个元素在格子内的水平对齐 */
justify-self: start; /* 或 center / end / stretch */
/* 单独设置这个元素在格子内的垂直对齐 */
align-self: center;
}5.3 对齐速查表
justify-* = 水平方向(左右)
align-* = 垂直方向(上下)
*-items = 设置所有子元素
*-content = 设置整体网格
*-self = 设置单个子元素六、实战练习
6.1 练习一:经典网页布局
<div class="layout">
<header class="header">头部导航</header>
<aside class="sidebar">侧边栏</aside>
<main class="content">主要内容区</main>
<footer class="footer">底部版权</footer>
</div>.layout {
display: grid;
min-height: 100vh;
grid-template-columns: 240px 1fr;
grid-template-rows: 60px 1fr 40px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.header {
grid-area: header;
background: #1a1a2e;
color: white;
display: flex;
align-items: center;
padding: 0 20px;
}
.sidebar {
grid-area: sidebar;
background: #16213e;
color: white;
padding: 20px;
}
.content {
grid-area: content;
background: #f5f5f5;
padding: 24px;
}
.footer {
grid-area: footer;
background: #1a1a2e;
color: white;
display: flex;
align-items: center;
justify-content: center;
}
/* 响应式:小屏幕改成上下排列 */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"content"
"sidebar"
"footer";
}
}6.2 练习二:响应式相册
<div class="gallery">
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
<div class="photo">📷</div>
</div>.gallery {
display: grid;
/* 核心:一行代码实现响应式! */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
padding: 16px;
}
.photo {
aspect-ratio: 1; /* 正方形 */
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
}💡 亮点:不管屏幕多宽多窄,相册都会自动调整每行的照片数量,每张照片至少 200px 宽!
6.3 练习三:仪表盘布局
<div class="dashboard">
<div class="card stats">统计概览</div>
<div class="card chart">图表区域</div>
<div class="card table">数据表格</div>
<div class="card todo">待办事项</div>
</div>.dashboard {
display: grid;
grid-template-columns: 2fr 1fr;
grid-template-rows: auto auto auto;
gap: 16px;
padding: 16px;
}
.stats {
/* 跨两列 */
grid-column: 1 / -1; /* -1 表示到最后一条线 */
background: #e3f2fd;
}
.chart {
/* 占据第一列,第二行 */
grid-column: 1;
grid-row: 2;
height: 300px;
background: #f3e5f5;
}
.table {
/* 占据第一列,第三行 */
grid-column: 1;
grid-row: 3;
height: 200px;
background: #e8f5e9;
}
.todo {
/* 占据第二列,跨第二和第三行 */
grid-column: 2;
grid-row: 2 / 4; /* 从第2行到第4行 */
background: #fff3e0;
}
.card {
border-radius: 8px;
padding: 16px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: bold;
}┌──────────────────────────────┐
│ 统计概览 │
├────────────────┬─────────────┤
│ │ │
│ 图表区域 │ 待办事项 │
│ │ │
├────────────────┤ │
│ │ │
│ 数据表格 │ │
│ │ │
└────────────────┴─────────────┘6.4 练习四:圣杯布局
经典的「圣杯布局」(Holy Grail Layout):
<div class="holy-grail">
<header>头部</header>
<nav>导航</nav>
<main>主内容</main>
<aside>侧边栏</aside>
<footer>底部</footer>
</div>.holy-grail {
display: grid;
min-height: 100vh;
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: 12px;
padding: 12px;
}
header { grid-area: header; background: #1a1a2e; color: white; }
nav { grid-area: nav; background: #16213e; color: white; }
main { grid-area: main; background: #f5f5f5; }
aside { grid-area: aside; background: #16213e; color: white; }
footer { grid-area: footer; background: #1a1a2e; color: white; }
/* 所有区域通用样式 */
.holy-grail > * {
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
}
/* 响应式 */
@media (max-width: 768px) {
.holy-grail {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"nav"
"aside"
"footer";
}
}6.5 练习五:表单布局
用 Grid 对齐标签和输入框:
<form class="form">
<label>用户名</label>
<input type="text" placeholder="请输入用户名">
<label>邮箱</label>
<input type="email" placeholder="请输入邮箱">
<label>个人简介</label>
<textarea placeholder="请输入简介"></textarea>
<div></div>
<button type="submit">提交</button>
</form>.form {
display: grid;
grid-template-columns: 100px 1fr; /* 标签100px,输入框撑满 */
gap: 12px 16px; /* 行间距12px,列间距16px */
max-width: 500px;
}
.form label {
text-align: right;
line-height: 36px; /* 和输入框等高 */
}
.form input,
.form textarea {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
}
.form textarea {
height: 80px;
resize: vertical;
}
.form button {
grid-column: 2; /* 按钮放在第二列 */
justify-self: start; /* 靠左对齐 */
padding: 8px 24px;
background: #4a90d9;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}七、高级技巧
7.1 minmax() 函数
设置列宽的范围:
.grid {
display: grid;
/* 每列最少200px,最多1fr */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* 侧边栏最少200px,最多300px */
grid-template-columns: minmax(200px, 300px) 1fr;
}7.2 auto 关键字
让行或列根据内容自动计算:
.grid {
display: grid;
/* 中间列根据内容撑开,两边均分 */
grid-template-columns: 1fr auto 1fr;
}7.3 嵌套 Grid
Grid 可以嵌套使用:
.outer {
display: grid;
grid-template-columns: 200px 1fr;
}
.sidebar {
/* 侧边栏内部也用 Grid */
display: grid;
grid-template-rows: auto auto auto;
gap: 8px;
}
.content {
/* 内容区用 Grid 做卡片列表 */
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
}7.4 Grid + Flexbox 混合使用
实际开发中,Grid 和 Flexbox 经常配合使用:
/* Grid 负责整体布局 */
.page {
display: grid;
grid-template-areas:
"header"
"main"
"footer";
grid-template-rows: 60px 1fr 40px;
min-height: 100vh;
}
/* Flexbox 负责头部内部排列 */
.header {
grid-area: header;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}💡 黄金法则:Grid 做「整体布局」,Flexbox 做「局部排列」。
八、常见问题
8.1 Grid 和 Flexbox 该选哪个?
| 需求 | 推荐 |
|---|---|
| 一行或一列的排列 | Flexbox |
| 多行多列的网格 | Grid |
| 整页布局 | Grid |
| 导航栏、按钮组 | Flexbox |
| 卡片居中 | Flexbox(更简单) |
| 响应式相册 | Grid(auto-fit 更方便) |
| 复杂表单对齐 | Grid |
8.2 为什么 grid-template-areas 不生效?
/* 问题:名字不匹配 */
.grid {
grid-template-areas:
"header header"
"main main";
}
.header {
grid-area: header; /* ✅ 匹配 */
}
.main-content {
grid-area: main; /* ❌ 不匹配!grid-template-areas 里写的是 "main",但要确保完全一致 */
}解决: 确保名字完全一致,且每个区域必须是矩形。
8.3 为什么子元素没有在格子里居中?
/* 问题:Grid 默认 stretch(拉伸),但子元素有固定尺寸时不会居中 */
.grid {
display: grid;
grid-template-columns: 200px 200px;
}
.item {
width: 100px; /* 固定宽度,但不在格子中间 */
}
/* 解决:加对齐属性 */
.grid {
display: grid;
grid-template-columns: 200px 200px;
justify-items: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}九、Grid 速查表
9.1 容器属性
| 属性 | 作用 | 常用值 |
|---|---|---|
display | 开启网格布局 | grid |
grid-template-columns | 定义列 | repeat(3, 1fr) |
grid-template-rows | 定义行 | 100px 1fr 60px |
grid-template-areas | 命名区域 | "header header" "sidebar main" |
gap | 间距 | 16px |
justify-items | 水平对齐(所有子元素) | center |
align-items | 垂直对齐(所有子元素) | center |
justify-content | 网格水平位置 | center |
align-content | 网格垂直位置 | center |
9.2 子元素属性
| 属性 | 作用 | 常用值 |
|---|---|---|
grid-column | 占据的列 | 1 / 3 或 span 2 |
grid-row | 占据的行 | 1 / 3 或 span 2 |
grid-area | 命名区域 | header |
justify-self | 单独水平对齐 | center |
align-self | 单独垂直对齐 | center |
9.3 常用单位
| 单位 | 含义 | 例子 |
|---|---|---|
px | 固定像素 | 200px |
fr | 按比例分配 | 1fr 2fr |
auto | 自动 | auto |
% | 百分比 | 50% |
minmax() | 范围 | minmax(200px, 1fr) |
repeat() | 重复 | repeat(3, 1fr) |
9.4 最常用组合
| 场景 | CSS |
|---|---|
| 等宽3列 | grid-template-columns: repeat(3, 1fr) |
| 响应式网格 | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) |
| 整页布局 | grid-template-areas: "header header" "sidebar main" "footer footer" |
| 跨列元素 | grid-column: 1 / -1 |
十、总结
回顾本教程的要点:
display: grid开启网格布局grid-template-columns定义列,最常用的单位是frrepeat()简化重复列的定义auto-fit + minmax()一行代码实现响应式网格grid-template-areas用画图的方式定义布局,最直观gap设置间距,行列可以分别设置- 网格线 用数字编号,
1 / 3表示从第1条线到第3条线 span N表示跨越 N 个格子- Grid 做整体布局,Flexbox 做局部排列 是最佳实践
-1表示最后一条网格线,grid-column: 1 / -1就是跨满整行
掌握了 Flexbox 和 Grid,你就拥有了 CSS 布局的全部武器库!
相关阅读: