前言PREFACE
在现代 Web 前端开发领域,页面布局始终是绕不开的核心课题。长久以来,开发者依靠 float 浮动、position 定位、Flexbox 弹性布局完成页面排版。
Flexbox 作为一维布局方案,擅长处理单行或者单列的内容排布,在横向对齐、均分空间等场景表现优异。但面对同时控制行与列的二维复杂布局——例如多列卡片网格、不规则混排模块、复杂后台仪表盘、杂志式图文排版时,Flexbox 会显得力不从心,需要大量嵌套容器、计算百分比宽度、书写冗余 hack 代码来实现效果,代码可读性差,维护成本居高不下。
CSS Grid(网格布局)是 W3C 标准化的原生二维布局系统,专门用来同时处理行和列,完美弥补 Flexbox 在二维场景的短板。它把页面划分为由行(row)、列(column)构成的网格轨道,我们可以把元素放置在网格任意单元格内,轻松实现过去需要大量 CSS、JS 才能完成的复杂排版。截至目前,主流浏览器 Chrome、Firefox、Safari、Edge 全部完整支持 Grid,生产环境已经可以放心落地使用。
本文将结合 10 个实战案例,完整拆解 Grid 容器属性、Grid 项目属性,对比 Flexbox 的适用边界,讲解响应式网格实现技巧、常见踩坑点,带你彻底吃透 Grid 布局,让页面结构开发更加灵活优雅,给响应式开发带来质的提升。
基础概念:搞懂 Grid 核心术语FUNDAMENTALS
学习 Grid 第一步,先理清这套布局体系的基础名词,分清容器(Grid Container)和项目(Grid Item),这是后续所有属性的基础。下面 7 张卡片本身就是用 repeat(auto-fit, minmax()) 排列的(案例①同款写法):
网格容器
给元素设置 display: grid 或 display: inline-grid,该元素就成为网格容器,它的直接子元素自动变成网格项目。
grid:块级网格,独占整行空间inline-grid:行内块,与其他行内元素并排
网格轨道
网格中每一行、每一列的空间就是轨道。grid-template-columns 定义列轨道尺寸,grid-template-rows 定义行轨道尺寸。轨道可使用 px、%、em、rem,还有 Grid 独有的 fr。
fr 单位
fr 代表剩余空间分配比例,是 Grid 最强大特性之一。1fr 代表分配一份剩余可用空间。如 1fr 2fr:第一列占 1 份、第二列占 2 份,剩余空间分成 3 份分配。fr 不会挤压固定 px 宽度的轨道,会扣除固定尺寸后再分配。
网格线
划分轨道的分割线,列网格线垂直方向,行网格线水平方向。网格线从 1 开始编号,也可以设置自定义名称。项目可以通过网格线编号,自由跨单元格摆放。
网格单元格
行和列交叉形成的最小格子,是网格的基础单元。
网格间隙
单元格之间的间距。row-gap 行间隙、column-gap 列间隙,简写 gap。旧版属性名 grid-gap 已废弃。gap 只产生项目之间的间距,不会在容器边缘产生外边距。
网格区域
由多个相邻单元格合并形成的矩形区域,可以给区域命名,直接把项目放置到命名区域,大幅降低复杂布局代码量。
只有直接子元素才是 Grid 项目,后代子元素不受 Grid 布局控制。
Grid 容器全部核心属性详解CONTAINER PROPERTIES
容器属性写在父容器上,用来定义整个网格的行列结构、间隙、对齐方式。
2.1 grid-template-columns / grid-template-rows
定义网格的列、行轨道大小。
.container {
display: grid;
/* 创建3列,宽度分别 200px 1fr 2fr */
grid-template-columns: 200px 1fr 2fr;
/* 创建2行,高度 120px auto */
grid-template-rows: 120px auto;
}repeat() 重复函数
当需要批量创建相同规格轨道,不需要重复书写,使用 repeat(重复次数, 轨道尺寸)。
/* 生成4列,每一列1fr */
grid-template-columns: repeat(4, 1fr);auto-fill / auto-fit —— 响应式网格核心
auto-fill:尽可能多生成轨道,填满容器宽度,轨道会保留占位空间;auto-fit:自动合并多余空轨道,把现有轨道拉伸填满容器,做自适应卡片列表优先选 auto-fit。
搭配 minmax() 实现不写媒体查询的响应式网格,经典万能写法:
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));每一列最小宽度 240px,最大 1fr;容器宽度足够就多排列,容器变窄自动减少列数,卡片自动换行,无需写 @media 媒体查询。
minmax(min, max)
定义轨道尺寸范围,轨道尺寸不会小于最小值,也不会大于最大值。minmax(200px, 1fr) 代表轨道最小 200px,最大占用 1 份剩余空间。
2.2 gap 间隙属性
.container{
row-gap: 20px; /* 行与行之间间距 */
column-gap: 16px; /* 列与列之间间距 */
gap: 20px 16px; /* 简写:行间隙 列间隙 */
gap: 20px; /* 行列间隙统一20px */
}2.3 grid-template-areas 命名网格区域
给网格单元格划分命名区域,配合项目属性 grid-area,像画图一样写布局,非常适合页面整体大框架布局(头部、侧边栏、主内容、底部)。
.container{
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: 80px 1fr 60px;
/* 定义区域:三行,每行两个区域名称 */
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; }引号内每一组代表一行,同名区域代表单元格合并;不需要使用的区域用 . 点占位。
2.4 对齐属性:容器内全部项目对齐
Grid 两套对齐轴:
- 块轴:行方向、垂直方向对齐,属性
align-items; - 内联轴:列方向、水平方向对齐,属性
justify-items。
简写:place-items: align-items justify-items。可选值:
stretch(默认):项目拉伸填满单元格;start:对齐单元格起始边缘;end:对齐单元格结束边缘;center:单元格居中。
.container{
display: grid;
place-items: center center; /* 所有项目在单元格内水平垂直居中 */
}justify-items / align-items 作用于单元格内部的项目;justify-content / align-content 作用于整个网格轨道整体——当轨道总尺寸小于容器尺寸时生效(例如轨道都是固定 px 宽度,容器比轨道总宽更大)。
place-content 是 align-content justify-content 简写。可选值:start end center space-around space-between space-evenly stretch。
.container{
display: grid;
width: 1200px;
grid-template-columns: repeat(3, 200px);
justify-content: center; /* 网格整体在容器水平方向居中 */
}2.5 grid-auto-columns / grid-auto-rows 隐式轨道
当网格项目数量超出我们定义好的行列,浏览器会自动生成隐式网格轨道。我们可以控制这些自动生成轨道的尺寸。
.container{
display: grid;
grid-template-rows: 100px; /* 只定义1行 */
grid-auto-rows: 80px; /* 多出的自动行高度统一80px */
}2.6 grid-auto-flow 自动放置规则
控制多余项目自动填充网格的顺序。
row默认:优先按行填充;column:优先按列填充;row dense / column dense:密集模式,自动填充空白格子,会打乱 DOM 顺序,谨慎使用。
2.7 grid 综合简写属性
grid 可以一次性简写 grid-template-rows / columns / areas、grid-auto-rows / columns、grid-auto-flow。可读性差,业务开发不推荐大量使用简写,优先分开书写便于维护。
Grid 项目属性ITEM PROPERTIES
项目属性写在子元素上,控制单个网格项目:跨越单元格、定位网格线、单独修改对齐方式。
3.1 grid-column-start / end,grid-row-start / end
通过网格线编号控制项目占据哪几条网格线,实现跨列、跨行。
grid-column-start:列起始网格线;grid-column-end:列结束网格线;grid-row-start:行起始网格线;grid-row-end:行结束网格线。
关键字 span N:代表跨越 N 个轨道。
.item{
/* 列方向,从第1条网格线,跨2个单元格(占2列) */
grid-column-start: 1;
grid-column-end: span 2;
}简写:grid-column: start / end、grid-row: start / end
.item{
grid-column: 1 / span 2;
grid-row: 2 / 4;
}3.2 grid-area
双重作用:既可以搭配 grid-template-areas 使用区域名称;也可以简写网格线定位:grid-area: row-start / column-start / row-end / column-end
3.3 justify-self / align-self / place-self
单独修改某一个项目在单元格内部对齐,会覆盖容器设置的 justify-items / align-items。可选值:start end center stretch
.item{
/* 当前项目在单元格内水平垂直居中 */
place-self: center;
}Grid vs Flexbox:怎么选?GRID VS FLEXBOX
很多新手会疑惑,Grid 和 Flexbox 该如何取舍——二者不是替代关系,而是互补关系。
| 特性 | Flexbox | CSS Grid |
|---|---|---|
| 维度 | 一维布局,只能处理行或者列,单方向 | 二维布局,同时控制行 + 列 |
| 核心能力 | 内容优先,根据子元素内容伸缩尺寸 | 轨道优先,先定义网格行列结构,再放置元素 |
| 跨行跨列 | 实现跨行跨列非常麻烦,需要嵌套 | 原生支持任意跨行跨列,代码简洁 |
| 自适应 | 适合导航栏、单行列表、按钮组、居中对齐 | 卡片网格、仪表盘、整体页面骨架、不规则混排 |
| 嵌套成本 | 复杂二维场景需要多层嵌套容器 | 大多场景单容器即可完成 |
最佳实践:
- 一维场景优先 Flexbox:导航栏、按钮组、单行横向排列、垂直居中;
- 二维场景优先 Grid:卡片列表、后台布局、杂志图文混排、多行列不规则模块;
- 混合使用:Grid 做大页面整体骨架,Grid 单元格内部,再用 Flexbox 处理内部一维内容。
不要所有布局全部用 Grid,简单单行布局使用 Flexbox 代码更轻量。
10 个实战案例,吃透 Grid 落地TEN CASES
基础等宽卡片网格
需求:4 列卡片列表,卡片之间有间隙,响应式下自动减少列数。
<div class="card-wrap">
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
<div class="card">卡片4</div>
<div class="card">卡片5</div>
</div>.card-wrap{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 24px 20px;
}
.card{
padding: 16px;
background: #fff;
border-radius: 8px;
}无需媒体查询,浏览器宽度变化自动调整每行列数,这是生产环境最常用的卡片网格写法。
经典后台管理系统布局(头部、侧边栏、主内容区、底部)
需求:使用 grid-template-areas 区域命名,完成后台框架。
.layout{
height: 100vh;
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr 50px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; background: #222; color: #fff; }
.sidebar { grid-area: sidebar; background: #333; color: #fff; }
.main { grid-area: main; padding: 20px; overflow: auto; }
.footer { grid-area: footer; background: #222; color: #fff; }整个页面只需要一个父容器,完成传统需要嵌套多层 div 的后台布局。(你现在看到的这个页面,骨架就是它的变体。)
合并单元格,不规则网格相册
需求:相册模块,部分图片占 2 格大小。
.gallery{
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.big-item{
grid-column: span 2;
grid-row: span 2;
}完全居中(水平垂直居中)
需求:传统居中需要各种 hack,Grid 一行完成容器内所有子元素居中。
.box{
width: 500px;
height: 400px;
display: grid;
place-items: center;
}固定侧边栏 + 自适应主内容
需求:左侧侧边栏固定宽度,右侧内容自动占满剩余空间。
.wrap{
display: grid;
grid-template-columns: 260px 1fr;
gap: 20px;
}隐式轨道自动高度
需求:只定义 2 列,不限制行数,新增项目自动生成行,并且统一隐式行高度。
.list{
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: 100px;
gap: 16px;
}网格项目单独对齐,局部特殊处理
需求:大部分项目居中,其中一个项目居左。
.container{
display: grid;
grid-template-columns: repeat(3, 1fr);
place-items: center;
}
.item-special{
place-self: start center;
}space-between 风格网格轨道整体分布
需求:轨道是固定 px 尺寸,轨道之间均分剩余容器空间。
.container{
display: grid;
grid-template-columns: repeat(4, 160px);
justify-content: space-between;
}命名网格线定位项目
需求:除了数字编号,网格线可以自定义名字,可读性更强。
.container{
display: grid;
grid-template-columns: [left-start] 200px [main-start] 1fr [main-end];
}
.box{
grid-column: main-start / main-end;
}Dense 密集填充模式
需求:填补网格空白单元格。注意 DOM 渲染顺序会被打乱,适合图片墙,不适合列表业务。
.wall{
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-flow: row dense;
gap: 10px;
}Grid 响应式开发实战技巧RESPONSIVE
- auto-fit + minmax 优先,尽可能减少媒体查询。绝大多数卡片网格,不需要写
@media即可完成基础自适应。
2. 需要强定制布局时,配合媒体查询修改 grid-template-columns:
.container{
display: grid;
grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 992px){
.container{ grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 576px){
.container{ grid-template-columns: 1fr; }
}3. 小屏设备下直接取消网格布局,降级为块布局:
@media (max-width: 576px){
.layout{ display: block; }
}4. fr 单位不要搭配百分比混用计算,fr 已经自动扣除 gap 间隙,避免尺寸计算混乱。
高频踩坑问题与避坑指南PITFALLS
gap 产生横向滚动条
容器总宽度 = 轨道宽度总和 + gap 总和,容器宽度不足时会溢出。
只有直接子元素才是 Grid 项目
很多新手把子元素内部 DOM 当成网格项目,布局完全失效。
混淆 justify-items 与 justify-content
justify-items 控制单元格内部子元素对齐;justify-content 控制全部网格轨道整体对齐。
auto-fit 和 auto-fill 分不清
auto-fill 会生成空轨道,容器很宽时看到空白占位;auto-fit 自动折叠空轨道,现有轨道拉伸填满容器。
grid-auto-flow: dense 打乱 DOM 顺序
dense 模式会回填空白格子,视觉顺序和 HTML DOM 顺序不一致,屏幕阅读器、无障碍访问会出问题。
高度塌陷问题
Grid 容器设置 height: 100vh 后,内部主内容区域内容溢出不会自动滚动。
overflow: auto。不要滥用 Grid 做全部布局
简单导航、单行按钮组,Flexbox 实现代码更简单。
浏览器兼容与生产环境建议COMPATIBILITY
1. 以下版本起全部原生支持 Grid,现代业务项目完全可以直接上:
2. 如果需要兼容非常老旧浏览器(IE11):IE 支持老版本 Grid 语法,属性有大量兼容差异,建议使用降级方案,直接回退到 float / Flexbox。
3. 开发调试技巧:浏览器开发者工具 Elements 面板,选中 Grid 容器,点击 grid 标签,浏览器会高亮网格线、单元格,直观查看网格结构,调试效率极高——本页首屏的"网格解剖图"就是它的样子。
交互实验室:亲手调一个 GridPLAYGROUND
拖动滑块,或抓住预览区右下角横向拉伸容器宽度,右侧代码实时同步;开启 auto-fit 后观察列数随宽度自动增减——这正是案例①的运行机制。
3 列
总结SUMMARY
CSS Grid 是 CSS 有史以来最强大的布局系统,重新定义了 Web 二维布局的开发模式:
- 核心思想:先定义网格轨道结构,再放置元素。fr 单位、auto-fit、minmax 是三大最强特性。
- 容器属性定义网格行列、间隙、对齐;项目属性控制单个子元素跨单元格、定位。
- Grid 不是用来完全替代 Flexbox,二者各司其职:一维选 Flexbox,二维选 Grid,开发中常常组合使用。
- auto-fit + minmax 可以实现零媒体查询自适应网格,大量减少响应式代码。
- 善用浏览器网格调试工具,理清容器、项目、隐式轨道概念,避开常见坑。
掌握 Grid 之后,过去复杂、需要大量嵌套 hack 的页面排版,现在只需要简洁的 CSS 代码即可完成,页面结构更加优雅清晰,大幅降低维护成本,让响应式开发如虎添翼。