CSS Grid 网格布局
学习 display:grid 进行二维布局 · 难度:进阶 · +15XP
CSS Grid 网格布局
CSS Grid Layout 是 CSS 最强大的二维布局系统。它可以同时控制行(rows)和列(columns),让你像在 Excel 表格中一样精确地放置元素。Grid 非常适合做页面整体布局和复杂的二维排列。
Grid 核心概念
- Grid 容器(Grid Container):设置了
display: grid或display: inline-grid的元素 - Grid 项目(Grid Items):容器的直接子元素
- 网格线(Grid Lines):构成网格结构的水平和垂直分割线,用数字编号(从 1 开始)
- 网格轨道(Grid Tracks):两条相邻网格线之间的空间——即行或列
- 网格单元格(Grid Cell):一行和一列的交汇处,类似表格的单元格
- 网格区域(Grid Area):由多条网格线围成的矩形区域
容器属性速查表
| 属性 | 作用 | 常用示例 |
|---|---|---|
display |
激活 Grid 布局 | grid, inline-grid |
grid-template-columns |
定义列的数量和宽度 | repeat(3, 1fr), 200px 1fr 200px |
grid-template-rows |
定义行的数量和高度 | auto 1fr auto, repeat(2, 200px) |
gap / row-gap / column-gap |
行列间距 | gap: 20px, gap: 10px 20px |
grid-template-areas |
命名模板区域(语义化布局神器) | "header header" "sidebar main" |
justify-items |
单元格内水平对齐 | center, start, end, stretch |
align-items |
单元格内垂直对齐 | center, start, end, stretch |
justify-content |
整个网格在容器内的水平对齐 | center, space-between |
align-content |
整个网格在容器内的垂直对齐 | center, space-between |
grid-auto-rows |
隐式创建的行的高度 | minmax(100px, auto) |
grid-auto-columns |
隐式创建的列的宽度 | 150px |
grid-auto-flow |
自动放置算法 | row(默认), column, dense |
项目属性速查表
| 属性 | 作用 | 示例 |
|---|---|---|
grid-column |
定义项目占哪些列 | 1 / 3(从第 1 线到第 3 线),span 2 |
grid-row |
定义项目占哪些行 | 1 / 3,span 2 |
grid-area |
指定项目放置到哪个命名区域 | header, sidebar |
justify-self |
单个项目的水平对齐 | center, start, end |
align-self |
单个项目的垂直对齐 | center, start, end |
fr 单位详解(Grid 的核心创新)
/* fr = fraction(份数),表示可用空间中的份额 */
/* 3 列等宽 */
grid-template-columns: 1fr 1fr 1fr; /* 各占 1/3 */
/* 简写 */
grid-template-columns: repeat(3, 1fr);
/* 混合使用 —— 固定 + 弹性 */
grid-template-columns: 200px 1fr 2fr;
/* 第 1 列固定 200px,剩余空间按 1:2 分配给第 2、3 列 */
/* fr 与百分比的区别:
百分比不考虑 gap,fr 自动扣除 gap 后再分配 */
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
/* 每列宽度 = (容器宽 - 40px) / 3 ← fr 自动减掉 gap */
repeat() 和 minmax() 函数
/* repeat(次数, 尺寸) —— 重复定义轨道 */
grid-template-columns: repeat(12, 1fr); /* 12 等分栅格 */
grid-template-columns: repeat(3, 100px 200px); /* 重复模式:100, 200, 100, 200, 100, 200 */
/* minmax(最小值, 最大值) —— 轨道尺寸范围 */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
/* 自动填充:每列最小 250px,最大 1fr,列数自动计算 */
/* auto-fit vs auto-fill */
/* auto-fill:有空位就保留空轨道 */
/* auto-fit:有空位就拉伸现有项目填满 */
经典布局模式
1. 页面整体布局(grid-template-areas 方式)
<style>
.page {
display: grid;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
grid-template-columns: 250px 1fr 300px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
gap: 16px;
}
.header { grid-area: header; background: #333; color: white; padding: 20px; }
.sidebar { grid-area: sidebar; background: #f5f5f5; padding: 20px; }
.main { grid-area: main; padding: 20px; }
.aside { grid-area: aside; background: #f5f5f5; padding: 20px; }
.footer { grid-area: footer; background: #333; color: white; padding: 20px; }
</style>
<div class="page">
<header class="header">头部导航</header>
<nav class="sidebar">侧边导航</nav>
<main class="main">主要内容</main>
<aside class="aside">右侧信息栏</aside>
<footer class="footer">页脚信息</footer>
</div>
2. 响应式卡片网格(auto-fill + minmax)
<style>
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
padding: 24px;
}
.card {
background: white;
border: 1px solid #e0e0e0;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
</style>
<div class="card-grid">
<div class="card">卡片 1</div>
<div class="card">卡片 2</div>
<div class="card">卡片 3</div>
<div class="card">卡片 4</div>
<!-- 自动换行,无需写媒体查询! -->
</div>
<!-- 一行代码实现响应式:
窗口宽时显示 4 列,窗口窄时自动减少列数 -->
3. 仪表盘布局(项目跨行跨列)
<style>
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 150px);
gap: 16px;
}
.stat1 { grid-column: span 2; grid-row: span 1; } /* 宽 2 列 */
.stat2 { grid-column: span 1; grid-row: span 1; }
.stat3 { grid-column: span 1; grid-row: span 1; }
.chart1 { grid-column: span 2; grid-row: span 2; } /* 大图表占 2x2 */
.chart2 { grid-column: span 2; grid-row: span 2; }
</style>
<div class="dashboard">
<div class="stat1">总用户数</div>
<div class="stat2">今日新增</div>
<div class="stat3">活跃用户</div>
<div class="chart1">折线图</div>
<div class="chart2">饼图</div>
</div>
4. 十二列栅格系统
<style>
.grid-12 {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 20px;
}
.col-1 { grid-column: span 1; }
.col-2 { grid-column: span 2; }
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; } /* 半宽 */
.col-8 { grid-column: span 8; } /* 2/3 宽 */
.col-12 { grid-column: span 12; } /* 全宽 */
@media (max-width: 768px) {
.grid-12 { grid-template-columns: 1fr; } /* 移动端堆叠 */
[class*="col-"] { grid-column: span 1; }
}
</style>
Grid 与 Flexbox 场景对照
| 场景 | 推荐 | 原因 |
|---|---|---|
| 页面整体布局(header/sidebar/main/footer) | Grid | 同时控制行和列,grid-template-areas 直观 |
| 水平导航菜单 | Flexbox | 单行排列,内容驱动宽度 |
| 卡片网格(固定列宽) | Grid | auto-fill + minmax 一行搞定响应式 |
| 垂直居中一个元素 | Flexbox | 简单直接,不需要定义网格结构 |
| 仪表盘(不规则网格) | Grid | grid-column/row 跨行跨列能力 |
| 标签云、面包屑 | Flexbox | 内容长度不一,自动换行即可 |
| 表单布局(label + input) | Grid | 两列对齐,label 固定宽度效果完美 |
| 产品列表(不定数量) | 两者皆可 | 简单列用 Flexbox + wrap,严格对齐用 Grid |
常见陷阱与注意事项
/* 1. Grid 项目默认是 stretch —— 高度会撑满整行 */
/* 如果不想要,设置 align-items: start 或 align-self: start */
/* 2. z-index 在 Grid 中有效 —— 项目可以层叠 */
.item { grid-column: 1 / 3; grid-row: 1 / 3; z-index: 1; }
/* 3. 绝对定位的子元素:如果 Grid 容器有 position: relative,
子绝元素的包含块是它的网格区域,而不是整个容器 */
.container { position: relative; display: grid; }
.item { position: absolute; top: 0; } /* 定位在网格区域内 */
/* 4. 空轨道不会自动收缩 —— 用 auto-fit 让它们折叠 */
/* 5. Grid 中的 margin 不会折叠 —— 可以安全使用 */
/* 6. Grid 布局不会影响文档流中的兄弟元素 */
???? 练习任务
- 用
grid-template-areas实现经典页面布局:Header / Sidebar / Main / Aside / Footer - 用
repeat(auto-fill, minmax(250px, 1fr))实现无需媒体查询的响应式卡片网格 - 实现一个 12 列栅格系统,支持
.col-1到.col-12,移动端自动堆叠 - 用 Grid 的
grid-column和grid-row实现一个仪表盘布局,包含不同大小的区块 - 用 Grid 制作一个对齐整齐的表单(label 和 input 各一列)
- 对比同一个布局用 Flexbox 和 Grid 分别实现,体会两者的差异