CSS Grid 布局完全指南:从入门到实战
CSS Grid 是强大的二维布局系统。本文从基础概念到高级技巧,带你全面掌握 Grid 布局,并配有大量实战代码示例。
为什么是 Grid 而不是 Flex
Flexbox 是一维布局(要么横排要么竖排),Grid 是二维的——同时控制行和列。
实际开发中,页面整体布局用 Grid,组件内部用 Flex,两者配合着用,不是二选一。
一个典型的场景:后台管理页面的侧边栏 + 顶栏 + 内容区,用 Grid 两行两列就搞定了,用 Flex 得嵌套好几层。
基础概念
容器和项目
.container {
display: grid; /* 生成块级网格 */
/* display: inline-grid; 行内网格 */
}
直接子元素自动成为网格项目(grid item),跟 Flex 一样。
网格线(Grid Lines)
Grid 最核心的概念。网格线是用数字编号的,从左上角开始,列线 1、2、3...,行线 1、2、3...
后面所有的定位都是基于这些线编号来的。
定义行和列
grid-template-columns / grid-template-rows
.container {
display: grid;
grid-template-columns: 200px 1fr 300px;
grid-template-rows: 60px 1fr 40px;
}
上面这个定义:3列(固定200、自适应、固定300)+ 3行(固定60、自适应、固定40),典型的后台布局。
repeat() 函数
写一堆重复值太烦,用 repeat():
.container {
/* 4 列,每列 1fr */
grid-template-columns: repeat(4, 1fr);
/* 等价于:200px 200px 200px 1fr 1fr */
grid-template-columns: repeat(3, 200px) repeat(2, 1fr);
}
minmax() 函数
设置最小值和最大值,自适应布局非常有用:
.container {
/* 每列最小 200px,最大 1fr(等分) */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
这行代码实现了一个**响应式网格**:容器变窄时自动减少列数,不用写媒体查询。
项目定位
按网格线定位(最常用)
.sidebar {
grid-column: 1 / 2; /* 占第1根列线到第2根列线(即第1列) */
grid-row: 2 / 3; /* 第2行 */
}
.main {
grid-column: 2 / 4; /* 占第2、3列 */
grid-row: 2 / 3;
}
.header {
grid-column: 1 / 4; /* 横跨所有列 */
grid-row: 1 / 2;
}
简写方式 grid-column: 1 / 3 意思是"从列线1开始,到列线3结束",占两列。
grid-area(语义化命名)
先给容器定义区域名称:
.container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: 60px 1fr 40px;
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; }
这种写法可读性非常好,布局变更时只改 grid-template-areas 那几行字符串就行,不用改每个项目的定位。
间距和对齐
gap(间距)
以前用 grid-gap,现在标准属性是 gap(Flexbox 也能用):
.container {
gap: 16px; /* 行列间距都是 16px */
/* gap: 16px 24px; 行间距 16px,列间距 24px */
}
不用再写 margin 模拟间距了,Grid 原生支持。
容器内对齐(justify-content / align-content)
当网格总尺寸小于容器时生效:
.container {
justify-content: center; /* 水平居中 */
align-content: center; /* 垂直居中 */
}
可选值:start、end、center、space-between、space-around、space-evenly。
项目内对齐(justify-self / align-self)
控制单个项目在自己的网格区里怎么对齐:
.item {
justify-self: center; /* 水平居中 */
align-self: center; /* 垂直居中 */
}
实战:后台管理布局
.app {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 56px 1fr 48px;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
height: 100vh;
}
.header { grid-area: header; background: #001529; color: #fff; }
.sidebar { grid-area: sidebar; background: #f0f2f5; }
.main { grid-area: main; padding: 24px; overflow: auto; }
.footer { grid-area: footer; border-top: 1px solid #e8e8e8; }
HTML 结构只需要:
<div class="app">
<header class="header">顶栏</header>
<aside class="sidebar">侧边栏</aside>
<main class="main">内容区</main>
<footer class="footer">底栏</footer>
</div>
没有嵌套 div,没有 float,没有 calc——这就是 Grid 的优势。
实战:响应式卡片列表
.card-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
padding: 24px;
}
/* 不需要媒体查询! */
/* 屏幕够宽时自动显示更多列 */
auto-fill 和 auto-fit 的区别:
一般用 auto-fit 体验更好。
常见坑
坑1:项目溢出网格
如果项目定位超出了定义的网格,Grid 会自动生成隐式网格轨道,但尺寸默认是 auto(内容撑开),可能很丑。
解决方法:设置 grid-auto-rows 或 grid-auto-columns 指定隐式轨道大小:
.container {
grid-auto-rows: minmax(100px, auto);
}
坑2:fr 单位没想象中智能
1fr 是"剩余空间等分",不是"平分容器"。如果某个项目内容特别长,1fr 的列会被撑开,剩下的才参与等分。
坑3:IE11 不支持
如果你还要兼容 IE11——那就别用 Grid,或者做好降级(Grid 不生效时 fallback 到 Flexbox)。
总结
Grid 最擅长的是**页面级整体布局**和**二维对齐场景**。记住几个核心属性就能应付大部分需求:
> **Pro Tip**: Chrome DevTools 的 Layout 面板可以可视化网格线编号,调试 Grid 布局时开着,不用自己数线号。