跳转到内容

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

CSS Grid 网格布局从入门到实战

学会了 Flexbox 之后,你可能会遇到更复杂的布局需求:比如把页面分成「头部、侧边、内容、底部」四个区域,或者做一个相册网格。这时候 CSS Grid 就登场了!Grid 是比 Flexbox 更强大的二维布局系统,这篇教程继续用大白话带你从零掌握。


一、Grid 和 Flexbox 有什么区别?

1.1 通俗对比

特性FlexboxGrid
维度一维(一行或一列)二维(行和列同时)
比喻排队桌子摆盘子
适用场景导航栏、按钮组、居中整页布局、相册、表格
控制方式从内容出发从容器出发

大白话理解:

  • Flexbox 就像排队——大家排成一行(或一列),重点是「排队的方向」
  • Grid 就像在桌子上摆盘子——先画好格子,再把盘子放到指定的格子里

1.2 什么时候用 Grid?

场景例子
整页布局头部 + 侧边栏 + 内容 + 底部
图片相册3×3 的照片网格
表单布局标签和输入框对齐
卡片网格商品列表、文章列表
仪表盘多个面板的复杂排列

1.3 最简单的例子

html
<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>
css
.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 中最重要的属性,用来定义有多少列、每列多宽:

css
.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

css
.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() 更简洁:

css
.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(自动列数)

这两个值可以实现「自动响应式」,不需要写媒体查询!

css
.grid {
  display: grid;

  /* 自动适应:每列最少200px,放不下就换行 */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

这是 Grid 最强大的功能之一! 上面的代码会:

  • 屏幕宽时,自动多放几列
  • 屏幕窄时,自动减少列数
  • 每列最少 200px,剩余空间均分

auto-fitauto-fill 的区别:

  • auto-fit:空的格子会塌缩,让现有格子撑满
  • auto-fill:保留空格子位置

💡 99% 的情况下用 auto-fit 就对了!

2.5 grid-template-rows(定义行)

grid-template-columns 类似,用来定义行的高度:

css
.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 设置间距:

css
.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 用网格线定位子元素

css
.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 跨越的简写

css
/* 从第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 给区域命名

可以用名字来命名网格区域,非常直观:

css
.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 使用命名区域

css
.header {
  grid-area: header;
}

.sidebar {
  grid-area: sidebar;
}

.content {
  grid-area: content;
}

.footer {
  grid-area: footer;
}

💡 这是 Grid 最直观的用法! 画个「ASCII 图」就能定义布局,一目了然。

4.3 用点号表示空区域

css
.grid {
  grid-template-areas:
    "header  header  header"
    "sidebar .       content"
    "footer  footer  footer";
}

中间的 . 表示这个位置留空。

4.4 响应式布局(改变区域排列)

css
.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
css
.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 子元素对齐(单独)

css
.item {
  /* 单独设置这个元素在格子内的水平对齐 */
  justify-self: start;  /* 或 center / end / stretch */

  /* 单独设置这个元素在格子内的垂直对齐 */
  align-self: center;
}

5.3 对齐速查表

justify-*  = 水平方向(左右)
align-*    = 垂直方向(上下)
*-items    = 设置所有子元素
*-content  = 设置整体网格
*-self     = 设置单个子元素

六、实战练习

6.1 练习一:经典网页布局

html
<div class="layout">
  <header class="header">头部导航</header>
  <aside class="sidebar">侧边栏</aside>
  <main class="content">主要内容区</main>
  <footer class="footer">底部版权</footer>
</div>
css
.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 练习二:响应式相册

html
<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>
css
.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 练习三:仪表盘布局

html
<div class="dashboard">
  <div class="card stats">统计概览</div>
  <div class="card chart">图表区域</div>
  <div class="card table">数据表格</div>
  <div class="card todo">待办事项</div>
</div>
css
.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):

html
<div class="holy-grail">
  <header>头部</header>
  <nav>导航</nav>
  <main>主内容</main>
  <aside>侧边栏</aside>
  <footer>底部</footer>
</div>
css
.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 对齐标签和输入框:

html
<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>
css
.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() 函数

设置列宽的范围:

css
.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 关键字

让行或列根据内容自动计算:

css
.grid {
  display: grid;

  /* 中间列根据内容撑开,两边均分 */
  grid-template-columns: 1fr auto 1fr;
}

7.3 嵌套 Grid

Grid 可以嵌套使用:

css
.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 经常配合使用:

css
/* 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 不生效?

css
/* 问题:名字不匹配 */
.grid {
  grid-template-areas:
    "header header"
    "main main";
}

.header {
  grid-area: header;  /* ✅ 匹配 */
}

.main-content {
  grid-area: main;    /* ❌ 不匹配!grid-template-areas 里写的是 "main",但要确保完全一致 */
}

解决: 确保名字完全一致,且每个区域必须是矩形。

8.3 为什么子元素没有在格子里居中?

css
/* 问题: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 / 3span 2
grid-row占据的行1 / 3span 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

十、总结

回顾本教程的要点:

  1. display: grid 开启网格布局
  2. grid-template-columns 定义列,最常用的单位是 fr
  3. repeat() 简化重复列的定义
  4. auto-fit + minmax() 一行代码实现响应式网格
  5. grid-template-areas 用画图的方式定义布局,最直观
  6. gap 设置间距,行列可以分别设置
  7. 网格线 用数字编号,1 / 3 表示从第1条线到第3条线
  8. span N 表示跨越 N 个格子
  9. Grid 做整体布局,Flexbox 做局部排列 是最佳实践
  10. -1 表示最后一条网格线,grid-column: 1 / -1 就是跨满整行

掌握了 Flexbox 和 Grid,你就拥有了 CSS 布局的全部武器库!


相关阅读: