Skip to content

Grid 布局

CSS Grid 是专为二维布局设计的系统。如果说 Flexbox 擅长一维布局(行或列),那 Grid 就是处理复杂网格布局的利器。它让曾经需要复杂 CSS 技巧才能实现的布局变得简单直观。

基本概念#

容器与项目#

<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
</div>
.grid-container {
display: grid; /* 或 inline-grid */
}

核心术语#

定义网格#

grid-template-columns / grid-template-rows#

定义列和行的尺寸:

.grid {
display: grid;
grid-template-columns: 200px 200px 200px; /* 三列,每列 200px */
grid-template-rows: 100px 100px; /* 两行,每行 100px */
}

fr 单位#

fr(fraction)表示剩余空间的比例:

.grid {
grid-template-columns: 1fr 2fr 1fr; /* 比例 1:2:1 */
}
.grid {
grid-template-columns: 200px 1fr; /* 固定 + 自适应 */
}

repeat() 函数#

简化重复定义:

.grid {
grid-template-columns: repeat(3, 1fr); /* 三列等宽 */
grid-template-columns: repeat(4, 100px 200px); /* 重复模式 */
}

minmax() 函数#

定义尺寸范围:

.grid {
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* 每列最小 200px,最大平分剩余空间 */
}

auto-fill 和 auto-fit#

自动填充列数:

/* 自动创建尽可能多的 200px 列 */
.grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

auto-fill vs auto-fit

/* 容器宽 800px,项目 2 个 */
.auto-fill {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* 创建 4 列,后 2 列为空但占空间 */
}
.auto-fit {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* 2 列,每列 400px */
}

间距#

.grid {
gap: 20px; /* 行列间距相同 */
gap: 20px 10px; /* 行间距 列间距 */
row-gap: 20px;
column-gap: 10px;
}

放置项目#

基于网格线#

网格线从 1 开始编号:

.item {
grid-column-start: 1;
grid-column-end: 3; /* 跨越第 1 到第 3 条列线(即前两列) */
grid-row-start: 1;
grid-row-end: 2;
}
/* 简写 */
.item {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
/* 更简写 */
.item {
grid-area: 1 / 1 / 2 / 3; /* row-start / col-start / row-end / col-end */
}

span 关键字#

指定跨越的单元格数:

.item {
grid-column: 1 / span 2; /* 从第 1 列开始,跨 2 列 */
grid-row: span 3; /* 跨 3 行 */
}

负数网格线#

从末尾开始计数:

.full-width {
grid-column: 1 / -1; /* 从第一列到最后一列 */
}

网格区域#

命名区域#

.grid {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'header header header'
'sidebar main aside'
'footer footer footer';
min-height: 100vh;
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.main {
grid-area: main;
}
.aside {
grid-area: aside;
}
.footer {
grid-area: footer;
}

使用 . 表示空单元格:

.grid {
grid-template-areas:
'header header header'
'sidebar main .'
'footer footer footer';
}

对齐#

容器级对齐#

.grid {
/* 项目在单元格内的对齐(所有项目) */
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
place-items: center; /* 简写 */
/* 整个网格在容器内的对齐 */
justify-content: start | end | center | space-between | space-around |
space-evenly;
align-content: start | end | center | space-between | space-around |
space-evenly;
place-content: center;
}

项目级对齐#

.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
place-self: center;
}

隐式网格#

当项目超出定义的网格时,浏览器会自动创建隐式轨道:

.grid {
grid-template-columns: repeat(3, 1fr);
/* 只定义了列,行会自动生成 */
grid-auto-rows: 100px; /* 隐式行的高度 */
grid-auto-columns: 1fr; /* 隐式列的宽度 */
grid-auto-flow: row; /* 自动放置方向:row | column | dense */
}

dense 紧凑排列#

.grid {
grid-auto-flow: row dense;
/* 自动填补空白,可能打乱视觉顺序 */
}

实战案例#

响应式卡片网格#

.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
.card {
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}

无需媒体查询,自动响应容器宽度。

圣杯布局#

.layout {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
'header header header'
'nav main aside'
'footer footer footer';
min-height: 100vh;
gap: 1rem;
}
.header {
grid-area: header;
padding: 1rem;
background: #1f2937;
color: white;
}
.nav {
grid-area: nav;
padding: 1rem;
background: #f3f4f6;
}
.main {
grid-area: main;
padding: 1rem;
}
.aside {
grid-area: aside;
padding: 1rem;
background: #f3f4f6;
}
.footer {
grid-area: footer;
padding: 1rem;
background: #1f2937;
color: white;
}
/* 响应式 */
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
'header'
'nav'
'main'
'aside'
'footer';
}
}

仪表板布局#

.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: auto auto 1fr;
gap: 1rem;
padding: 1rem;
}
.stat-card {
padding: 1.5rem;
background: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.chart-large {
grid-column: span 2;
grid-row: span 2;
}
.chart-small {
grid-column: span 2;
}
.table-full {
grid-column: 1 / -1;
}

图片瀑布流#

.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: 10px;
gap: 10px;
}
.gallery-item {
border-radius: 8px;
overflow: hidden;
}
/* 根据图片高度设置不同的 span */
.gallery-item.tall {
grid-row: span 30;
}
.gallery-item.medium {
grid-row: span 20;
}
.gallery-item.short {
grid-row: span 15;
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
}

表单布局#

.form {
display: grid;
grid-template-columns: 120px 1fr;
gap: 1rem;
align-items: center;
}
.form label {
text-align: right;
color: #6b7280;
}
.form input,
.form textarea {
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 6px;
}
.form-full {
grid-column: 1 / -1;
}
.form-actions {
grid-column: 2;
display: flex;
gap: 0.5rem;
}
<form class="form">
<label>用户名</label>
<input type="text" />
<label>邮箱</label>
<input type="email" />
<label>简介</label>
<textarea rows="4"></textarea>
<div class="form-actions">
<button type="submit">保存</button>
<button type="button">取消</button>
</div>
</form>

Grid vs Flexbox#

场景GridFlexbox
一维布局(行或列)可以,但杀鸡用牛刀✅ 最佳选择
二维布局(行和列)✅ 最佳选择需要嵌套
内容驱动布局需要知道内容结构✅ 自动适应内容
精确控制布局✅ 网格线精确定位受限于主轴方向
响应式网格✅ auto-fill/auto-fit需要手动计算
项目对齐两个方向都容易主轴容易,交叉轴需技巧

🎯 最佳实践:

两者可以嵌套使用:

.page {
display: grid;
grid-template-columns: 250px 1fr;
}
.navbar {
display: flex;
justify-content: space-between;
}
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.card {
display: flex;
flex-direction: column;
}

常见问题#

🤔 网格项目没有填满单元格?

默认 align-itemsjustify-itemsstretch,检查是否被覆盖了。

🤔 如何让某个项目跨越整行?

.full-row {
grid-column: 1 / -1;
}

🤔 grid-template-areas 里的名字可以重复吗?

可以,同名区域会合并成一个矩形。但必须是矩形,L 形或不规则形状无效。

🤔 如何调试 Grid 布局?

Chrome/Firefox 开发者工具有专门的 Grid 调试器,可以可视化网格线和区域。


Grid 让复杂的二维布局变得简单。结合 Flexbox,你几乎可以实现任何设计稿。下一篇我们将学习响应式设计,掌握媒体查询和移动优先策略。