CSS Grid 是 CSS 有史以来最强大的布局系统。与 Flexbox 的一维布局不同,Grid 可以同时控制行和列两个维度,是实现复杂页面布局的终极解决方案。2024 年,Grid 在全球浏览器的支持率已超过 97%,完全可以放心使用。本文从基础到高级,带你全面掌握 CSS Grid。
1. 基础概念:容器与项目
Grid 布局由容器(grid container)和项目(grid items)组成。容器是设置了 display: grid 的元素,其直接子元素自动成为 grid 项目。
.container {
display: grid;
/* 定义列:三列等宽 */
grid-template-columns: 1fr 1fr 1fr;
/* 定义行:两行,第一行100px,第二行自适应 */
grid-template-rows: 100px auto;
/* 间距 */
gap: 20px;
}
.item {
background: #4F46E5;
border-radius: 8px;
}
fr 是 Grid 引入的新单位,表示"剩余空间的份数"。上面的例子中,三列各占 1fr,意思是把容器宽度分成三份,每列占一份。
grid-template-columns 的多种写法
/* 固定像素 */
grid-template-columns: 200px 200px 200px;
/* 混合单位 */
grid-template-columns: 200px 1fr 2fr;
/* 第一列200px,剩余空间按1:2分配给第二三列 */
/* repeat() 函数 */
grid-template-columns: repeat(3, 1fr);
/* 等同于 1fr 1fr 1fr */
/* 带最小最大值 */
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* 每列最小200px,最大1fr */
/* auto-fill vs auto-fit */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* auto-fill: 尽量多放列,即使列是空的 */
/* auto-fit: 空列会被折叠,已有的列会展开填满 */
2. 项目定位:用行列线定位元素
Grid 中每个单元格都有行列线编号,可以精确控制项目占据的位置和跨度。
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
}
/* 占两列宽 */
.item-wide {
grid-column: 1 / 3; /* 从第1条列线到第3条列线 */
/* 或:grid-column: span 2; 跨2列 */
}
/* 占两行高 */
.item-tall {
grid-row: 1 / 3; /* 从第1条行线到第3条行线 */
}
/* 指定具体位置 */
.item-specific {
grid-column: 2 / 4;
grid-row: 2 / 4;
}
/* 简写 */
.item {
grid-area: 1 / 2 / 3 / 4;
/* row-start / column-start / row-end / column-end */
}
3. 区域命名:更语义化的布局
当布局复杂时,行列线编号难以维护。Grid 提供了命名区域的方式,让布局代码读起来就像在画蓝图。
.layout {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main right"
"footer footer footer";
gap: 16px;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.right { grid-area: right; }
.footer { grid-area: footer; }
这种写法的好处是一眼就能看出页面结构。配合媒体查询,可以轻松实现响应式布局——只需在不同断点下重新定义 grid-template-areas。
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"right"
"footer";
}
}
4. 对齐方式:对齐容器内的所有项目
Grid 有两套对齐属性:一组控制内容在单元格内的对齐,一组控制整个网格在容器中的对齐。
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(2, 100px);
gap: 10px;
/* 单元格内对齐(项目级别) */
justify-items: center; /* 水平:start | end | center | stretch */
align-items: center; /* 垂直:start | end | center | stretch */
place-items: center; /* 简写 */
/* 整个网格在容器中的对齐(容器级别) */
justify-content: center; /* 水平 */
align-content: center; /* 垂直 */
}
记忆方法:*-items 控制单元格里的项目怎么放,*-content 控制整个网格在容器里怎么放。当容器比网格大时,*-content 才有效果。
5. 实战:响应式卡片网格
这是 Grid 最经典的应用场景——一行代码实现自适应的卡片网格,不需要媒体查询:
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
.card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
这段代码的精妙之处:auto-fit 让浏览器自动计算一行能放几列,minmax(280px, 1fr) 保证每列至少 280px 宽,空间够的时候等分。容器变窄时列数自动减少,变宽时列数自动增加,完全响应式。
6. Grid vs Flexbox:什么时候用哪个?
这是最常见的问题。简单的判断标准:
- 一维布局用 Flexbox:导航栏、按钮组、单行卡片列表
- 二维布局用 Grid:整页布局、图片墙、复杂表单
- 内容驱动用 Flexbox:项目尺寸由内容决定
- 布局驱动用 Grid:先有网格结构,再往里填内容
在实际项目中,两者经常配合使用:Grid 负责页面整体骨架,Flexbox 负责组件内部的细节对齐。搭配得当,几乎没有摆不平的布局。
7. 调试技巧
Chrome DevTools 对 Grid 有非常棒的调试支持:在 Elements 面板找到 grid 容器,点击 grid 标签旁的徽章,页面上会显示网格线、行号、列号和区域名称。还可以在 Layout 面板中调整显示选项,帮助你理解复杂的 Grid 布局。
7. 高级特性:子网格与 masonry
Subgrid(子网格)
子网格是 Grid 最期待的特性之一。它允许嵌套的 grid 容器继承父容器的行列定义,实现真正的嵌套对齐。在 subgrid 之前,嵌套 Grid 的对齐只能靠手动计算,非常麻烦。
.parent {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto auto;
gap: 20px;
}
.child {
grid-column: span 3;
display: grid;
/* 子网格:继承父级的列定义 */
grid-template-columns: subgrid;
/* 这样子元素会和父级网格对齐 */
}
Subgrid 在 Safari 16+ 和 Firefox 71+ 中已支持,Chrome 也在积极开发中。对于需要精确对齐的卡片布局,subgrid 将是游戏规则改变者。
Masonry 布局
Masonry(瀑布流)布局是 Pinterest 带火的一种布局方式——元素高度不同,像砌墙一样错落排列。过去实现瀑布流需要 JavaScript 库(如 Masonry.js),现在 Grid 的 masonry 值可以原生实现。
.masonry {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry; /* 瀑布流 */
gap: 16px;
}
目前 masonry 还在实验阶段,只有 Firefox 支持。在生产环境中,还是需要用 CSS columns 或 JavaScript 来实现瀑布流布局。
8. 常见布局模式
圣杯布局
经典的三栏布局——两侧边栏固定宽度,中间内容区自适应。用 Grid 实现极其简单:
.holy-grail {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"left main right"
"footer footer footer";
min-height: 100vh;
}
仪表盘布局
后台管理系统常见的侧边栏 + 顶部导航 + 内容区布局:
.dashboard {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 60px 1fr;
grid-template-areas:
"sidebar header"
"sidebar main";
height: 100vh;
}
.sidebar { grid-area: sidebar; overflow-y: auto; }
.header { grid-area: header; }
.main { grid-area: main; overflow-y: auto; }
9. 浏览器兼容性与降级方案
截至 2024 年,CSS Grid 在全球浏览器的支持率超过 97%,IE 11 是最后一个不支持的主流浏览器。如果你的项目还需要兼容 IE,可以用 @supports 做渐进增强:
/* 降级方案:用 float 或 flexbox */
.grid-container {
display: flex;
flex-wrap: wrap;
}
/* 支持 Grid 的浏览器使用 Grid */
@supports (display: grid) {
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
}
不过到了 2026 年,IE 已经彻底退出历史舞台,Grid 可以放心大胆地使用。甚至连一些较新的特性(如 aspect-ratio、clamp、container queries)都有很高的支持率。
10. 学习资源推荐
想要深入学习 CSS Grid,以下资源值得推荐:
- CSS-Tricks A Complete Guide to Grid:最全面的 Grid 指南,随时查阅
- Grid Garden:通过种花园的游戏学习 Grid,寓教于乐
- Grid by Example:Rachel Andrew 维护的 Grid 示例网站
- MDN Grid 文档:最权威的参考文档
- Layoutit Grid:可视化拖拽生成 Grid 代码
学习 Grid 的最好方式是动手实践。下次遇到布局需求时,强迫自己用 Grid 来实现,哪怕一开始写得慢。用不了一周,你就会发现 Grid 已经融入了你的肌肉记忆,再也回不到 float 和 position 的时代了。
11. 命名网格线
除了用数字引用网格线,还可以给网格线命名,让布局代码更语义化。
.container {
display: grid;
grid-template-columns:
[sidebar-start] 240px
[sidebar-end main-start] 1fr
[main-end];
grid-template-rows:
[header-start] 60px
[header-end content-start] 1fr
[content-end footer-start] auto
[footer-end];
}
.sidebar {
grid-column: sidebar-start / sidebar-end;
grid-row: header-start / footer-end;
}
.header {
grid-column: main-start / main-end;
grid-row: header-start / header-end;
}
命名网格线在复杂布局中特别有用。配合 -start 和 -end 后缀,还可以用区域名直接引用:
/* 如果有 sidebar-start 和 sidebar-end,就可以直接写 */
.sidebar {
grid-column: sidebar; /* 自动对应 sidebar-start 到 sidebar-end */
}
12. min()、max()、clamp() 与 Grid
CSS 的数学函数和 Grid 搭配使用,可以实现非常灵活的响应式布局。
.container {
display: grid;
/* 列宽在 200px 到 1fr 之间,不超过 300px */
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
gap: clamp(12px, 2vw, 24px); /* 间距响应式变化 */
}
/* clamp(min, preferred, max) 函数 */
/* 间距随视口宽度变化,但不小于 12px,不大于 24px */
gap: clamp(12px, 2vw, 24px);
这些 CSS 函数可以替代很多之前需要媒体查询才能实现的响应式效果,让代码更简洁。特别是 clamp(),在流体排版(fluid typography)和响应式间距中非常实用。
13. 常见坑点与解决方案
使用 Grid 时容易遇到一些意想不到的问题,这里列出几个最常见的坑和解决方案。
grid 项目内容溢出
Grid 项目默认最小宽度是内容宽度(min-width: auto),这可能导致网格项目超出预期宽度。解决方案是设置 min-width: 0 或使用 minmax(0, 1fr)。
/* 防止内容溢出网格 */
.grid-item {
min-width: 0;
overflow: hidden; /* 或 auto */
}
/* 列定义时使用 minmax(0, 1fr) 而不只是 1fr */
grid-template-columns: repeat(3, minmax(0, 1fr));
gap 的兼容性
Grid 的 gap 属性在较新的浏览器中才支持(Chrome 66+)。如果需要兼容老版本浏览器,可以用 padding + 负 margin 的方式模拟间距,或者用 PostCSS 的 gap 插件做降级。
总之,Grid 并不难,难的是从传统布局思维中跳出来。当你真正用 Grid 的方式思考布局时,会发现曾经复杂的页面布局,现在几行代码就能搞定。