CSS Grid 布局实战
一、Introduction(简介)
CSS Grid Layout(网格布局)是 CSS3 引入的二维布局系统,它能够同时控制行(rows)和列(columns),轻松实现复杂的多行多列对齐。与 Flexbox 的一维布局相比,Grid 专为页面整体架构而设计,是现代前端布局的两大核心支柱之一。
Grid 的核心思想是将容器划分为「网格轨道(grid tracks)」,轨道之间由「网格线(grid lines)」分隔,网格单元(grid cells)由行线和列线交叉形成。通过给项目指定起始和结束网格线,可以实现以往需要大量 float 和 position 才能做到的精准布局。
Grid 自 2017 年起获得主流浏览器全面支持(IE 除外),如今已成为 PC 和移动端响应式布局的首选方案。本篇将从基础概念出发,配合丰富的实战代码,帮助你快速掌握 CSS Grid。
---
二、基础语法(Properties)
2.1 容器属性(放在父元素上)
/* 1. 声明网格容器 */
display: grid; /* 块级网格容器 */
display: inline-grid; /* 行内网格容器 */
/* 2. 定义列轨道(重复 auto-fit/auto-fill 实现响应式) */
grid-template-columns: 100px 200px 100px; /* 固定三列 */
grid-template-columns: 1fr 1fr 1fr; /* 三列等宽(fr = fraction 单位) */
grid-template-columns: repeat(3, 1fr); /* 同上,简写形式 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* 响应式自动列 */
/* 3. 定义行轨道 */
grid-template-rows: 80px 1fr 60px;
/* 4. 行列间距(简写) */
gap: 16px; /* 行间距=列间距=16px */
row-gap: 10px;
column-gap: 20px;
grid-gap: 10px 20px; /* 已废弃,推荐 gap */
/* 5. 网格区域命名(配合 grid-area 使用) */
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
/* 6. 显式网格与隐式网格 */
grid-auto-rows: minmax(100px, auto); /* 自动创建的行的尺寸 */
/* 7. 对齐方式 */
justify-items: stretch | start | end | center; /* 水平对齐网格项目 */
align-items: stretch | start | end | center; /* 垂直对齐网格项目 */
place-items: center; /* align-items + justify-items 简写 */
/* 8. 整个网格在容器中的对齐 */
justify-content: center | start | end | stretch | space-between ...;
align-content: center | start | end | stretch | space-between ...;
place-content: center;
/* 9. grid-template-columns/rows 的简写(ES2023+) */
grid-template: 100px 1fr 60px / 200px 1fr; /* rows / columns */
2.2 项目属性(放在子元素上)
/* 1. 指定放置的列网格线(从第几条线到第几条线) */
grid-column: 1 / 3; /* 占据第1列到第3列(跨2列) */
grid-column: 1 / span 2; /* 跨2列 */
/* 2. 指定放置的行网格线 */
grid-row: 1 / 3;
/* 3. grid-column + grid-row 的简写 */
grid-area: 1 / 1 / 3 / 3; /* row-start / col-start / row-end / col-end */
/* 4. 使用模板区域名称定位 */
grid-area: header; /* 对应模板中的 "header" 区域 */
/* 5. 单独对齐(覆盖容器 align-items/justify-items) */
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
place-self: center;
/* 6. 网格线名称(了解即可) */
grid-column-start: col-start-1;
grid-column-end: col-end-1;
---
三、代码示例
示例一:经典 12 栅格系统
.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; }
.col-12 { grid-column: span 12; }
<div class="grid-12">
<div class="col-4" style="background:#3498db;color:white;padding:16px;">4列</div>
<div class="col-8" style="background:#e74c3c;color:white;padding:16px;">8列</div>
<div class="col-3" style="background:#2ecc71;color:white;padding:16px;">3列</div>
<div class="col-6" style="background:#f39c12;color:white;padding:16px;">6列</div>
<div class="col-3" style="background:#9b59b6;color:white;padding:16px;">3列</div>
</div>
运行效果: 精确的 12 列网格,任选列数相加不超过 12 自动换行。开发中只需组合不同 .col-* 类即可构建响应式页面布局。
---
示例二:响应式图片画廊(无媒体查询)
.gallery {
display: grid;
/* 关键:minmax(250px, 1fr) + auto-fit 让列数自动响应 */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 12px;
padding: 16px;
}
.gallery-item {
aspect-ratio: 1; /* 强制正方形 */
object-fit: cover;
width: 100%;
border-radius: 8px;
transition: transform 0.2s;
}
.gallery-item:hover { transform: scale(1.03); }
<div class="gallery">
<img class="gallery-item" src="photo1.jpg" alt="照片1">
<img class="gallery-item" src="photo2.jpg" alt="照片2">
<img class="gallery-item" src="photo3.jpg" alt="照片3">
<img class="gallery-item" src="photo4.jpg" alt="照片4">
<img class="gallery-item" src="photo5.jpg" alt="照片5">
</div>
运行效果: 完全不需要 @media 查询,窗口变窄自动增加行数,列数自动减少,每张图片保持正方形且宽度填满。极简代码实现专业级响应式画廊。
---
示例三:完整页面布局(Header + Sidebar + Content + Footer)
.page {
display: grid;
/* 定义页面行高:auto 由内容决定,1fr 填满剩余空间 */
grid-template-rows: auto 1fr auto;
grid-template-columns: 260px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
min-height: 100vh;
gap: 0;
}
.header { grid-area: header; background: #e74c3c; color: white; padding: 20px; }
.sidebar { grid-area: sidebar; background: #34495e; color: white; padding: 20px; }
.main { grid-area: main; background: #ecf0f1; padding: 20px; }
.footer { grid-area: footer; background: #2c3e50; color: white; padding: 16px; }
<div class="page">
<header class="header">网站头部</header>
<aside class="sidebar">侧边栏菜单</aside>
<main class="main">主内容区域</main>
<footer class="footer">网站底部</footer>
</div>
运行效果: 用 grid-template-areas 绘制布局示意图,代码可读性极强,侧边栏固定 260px,主内容区自动填充剩余空间,底部自动贴底,无需 JavaScript 计算。
---
示例四:圣杯 + 双栏响应式布局
.dashboard {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 60px 1fr 50px;
grid-template-areas:
"topbar topbar topbar"
"leftbar content rightbar"
"bottombar bottombar bottombar";
min-height: 100vh;
}
.topbar { grid-area: topbar; background: #3498db; color: white; }
.leftbar { grid-area: leftbar; background: #9b59b6; color: white; }
.content { grid-area: content; background: #f8f9fa; }
.rightbar { grid-area: rightbar; background: #1abc9c; color: white; }
.bottombar { grid-area: bottombar; background: #34495e; color: white; }
<div class="dashboard">
<div class="topbar">顶部导航</div>
<div class="leftbar">左侧栏</div>
<div class="content">主内容</div>
<div class="rightbar">右侧栏</div>
<div class="bottombar">底部</div>
</div>
运行效果: 经典三栏布局加顶部导航和底部,grid-area 命名让代码语义清晰。如需改为移动端单栏,只需在媒体查询中调整 grid-template-areas 和 grid-template-columns 即可。
---
四、运行效果总结
| 场景 | 关键属性 | 效果 |
|------|---------|------|
| 12 栅格系统 | grid-template-columns: repeat(12, 1fr) | 精确列控制,完美对齐 |
| 响应式画廊 | repeat(auto-fit, minmax(250px, 1fr)) | 无媒体查询自动响应 |
| 页面整体布局 | grid-template-areas + grid-area | 代码即设计稿,可读性极强 |
| 卡片网格 | gap + grid-template | 统一间距,无需计算 margin |
| 溢出拉伸 | justify-content: stretch | 项目填满整个容器 |
| 层叠网格项目 | z-index + grid-column/row | 支持跨行跨列叠加 |
| 隐式行自动高度 | grid-auto-rows: minmax(100px, auto) | 自动行高适应内容 |
---
五、常见问题(FAQ)
Q1:Grid 和 Flexbox 我该用哪个?
原则:
- <strong>Flexbox</strong>:适合组件内部的一维排列(按钮组、表单行、导航项、卡片内元素)
- <strong>Grid</strong>:适合页面整体架构的二维布局(整体页面、画廊、仪表盘、表格)
两者可共存:外层页面用 Grid,内部组件用 Flexbox。各司其职,互补而非替代。
---
Q2:<code>fr</code> 单位是什么?和百分比有什么区别?
fr(fraction,份额)是 Grid 专属单位,表示占可用空间的份额。
grid-template-columns: 1fr 2fr 1fr;
三列按 1:2:1 比例分配可用空间(注意:可用空间 = 容器宽度 - gap - 固定宽度列)。
与百分比的区别:% 是相对于容器宽度的比例,但 gap 不会参与 % 的计算,容易导致溢出。fr 则自动考虑 gap,更适合 Grid 场景。
---
Q3:<code>auto-fit</code> 和 <code>auto-fill</code> 有什么区别?
/* auto-fit:项目填满整行,多余空间由项目分享(放大) */
/* auto-fill:项目保持自身宽度,多余空间留空(不放大) */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
当项目数量少、无法填满一行时:
- <code>auto-fit</code> — 项目会放大填满整行
- <code>auto-fill</code> — 项目保持 minmax 最小值,右侧留白
---
Q4:Grid 项目跨越多行/列时如何精确控制?
.item {
grid-column-start: 2; /* 从第2列网格线开始 */
grid-column-end: 4; /* 到第4列网格线结束(跨2列) */
grid-row-start: 1;
grid-row-end: 3; /* 跨2行 */
}
也可使用命名网格线(开发中不常用):
grid-template-columns: [col-start] 200px [col-mid] 1fr [col-end];
.item { grid-column: col-start / col-end; }
---
Q5:如何让某个 Grid 项目不对齐到网格线(使用 margin 偏移)?
Grid 项目默认贴齐网格线。若要手动偏移,可在项目上使用 margin 或 position: relative:
.override-item {
grid-column: 1 / 3;
margin-left: 20px; /* 向右偏移20px */
}
---
Q6:Grid 兼容移动端 IE 吗?
IE11 支持旧版 Grid 语法(ms-grid-columns),但语法差异极大。若必须兼容 IE,建议使用 Flexbox 或 PostCSS 插件 autoprefixer + postcss-grid-autoplace。大多数项目 2024 年后已不再支持 IE,可放心使用标准 Grid。
---
六、延伸阅读
- <strong>MDN 官方文档</strong>:<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_grid_layout">CSS Grid Layout</a> — 最权威最全面的 Grid 参考
- <strong>CSS-Tricks Grid 完整指南</strong>:<a href="https://css-tricks.com/snippets/css/complete-guide-grid/">A Complete Guide to CSS Grid</a> — 配有可视化图解,强烈推荐
- <strong>Grid Garden</strong>:<a href="https://cssgridgarden.com/">Grid Garden</a> — 用游戏学习 Grid,适合巩固知识
- <strong>CSS Grid Generator</strong>:<a href="https://cssgridgenerator.io/">cssgridgenerator.io</a> — 可视化生成 Grid 代码的免费工具
- <strong>Google Web Dev — Grid 布局</strong>:<a href="https://web.dev/learn/css/grid">web.dev - CSS Grid</a> — 官方学习平台,系统教程
- <strong>Rachel Andrew 博客</strong>:<a href="https://gridbyexample.com/">Grid by Example</a> — CSS Grid 布道者的经典教程网站
---
*CSS Grid 配合 Flexbox,现代 CSS 布局的两大支柱已经就位。掌握这两者,任何复杂的页面结构都能用纯 CSS 优雅实现,再也不需要依赖 JavaScript 布局框架了。*