CSS: Grid 容器与行列
CSS Grid(网格布局)是一个二维布局系统,可以同时控制行和列。与 Flexbox 的一维布局不同,Grid 让你在水平和垂直方向上同时控制元素的位置和大小。
1. 什么是 Grid 布局?
💡 Grid vs Flexbox 的选择: 一维布局(单行/单列)用 Flexbox,二维布局(同时控制行和列)用 Grid。简单说:导航栏用 Flexbox,页面整体布局用 Grid。两者可以嵌套使用。
Grid 布局将页面划分为行(row)和列(column),形成一个网格。你可以把元素放入任意网格单元中,甚至可以跨行、跨列。这种布局方式非常适合制作复杂的页面结构。
(1) Grid 容器属性速查表
| 属性 | 常用值 | 作用 |
|---|---|---|
display |
grid, inline-grid |
启用网格布局(容器) |
grid-template-columns |
200px 1fr 200px, repeat(3, 1fr) |
定义列的宽度 |
grid-template-rows |
100px auto 100px, repeat(2, 1fr) |
定义行的高度 |
grid-template-areas |
"header header" "sidebar main" |
用命名区域定义网格 |
grid-template |
"header" 100px "main" 1fr / 1fr |
行列简写属性 |
gap / row-gap / column-gap |
20px, 10px 20px |
网格间距 |
justify-items |
stretch, start, end, center |
项目在列方向的对齐 |
align-items |
stretch, start, end, center |
项目在行方向的对齐 |
justify-content |
start, end, center, stretch, space-around, space-between, space-evenly |
整个网格在容器内的列对齐 |
align-content |
start, end, center, stretch, space-around, space-between, space-evenly |
整个网格在容器内的行对齐 |
grid-auto-rows |
100px, minmax(100px, auto) |
隐式行(超出定义的网格自动生成)的尺寸 |
grid-auto-columns |
100px, minmax(100px, auto) |
隐式列的尺寸 |
grid-auto-flow |
row, column, row dense, column dense |
自动排列方式 |
▶ 示例
HTML
<style>
.container {
display: grid; /* 启用网格布局 */
}
.container-item {
background: #e8f4f8;
border: 1px solid #3498db;
padding: 16px;
margin: 4px;
border-radius: 4px;
text-align: center;
}
</style>
<div class="container">
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
</div>
2. 定义网格结构
(1) grid-template-columns:定义列
▶ 示例
HTML
<style>
.container {
display: grid;
grid-template-columns: 200px 300px 200px; /* 三列,宽度分别为200、300、200 */
}
.container-item {
background: #e8f4f8;
border: 1px solid #3498db;
padding: 16px;
margin: 4px;
border-radius: 4px;
text-align: center;
}
</style>
<div class="container">
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
</div>
(2) grid-template-rows:定义行
▶ 示例
HTML
<style>
.container {
display: grid;
grid-template-rows: 100px 200px; /* 两行,高度分别为100和200 */
}
.container-item {
background: #e8f4f8;
border: 1px solid #3498db;
padding: 16px;
margin: 4px;
border-radius: 4px;
text-align: center;
}
</style>
<div class="container">
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
</div>
(3) fr 单位(弹性尺寸)
📌 fr 的妙用:
fr 是 Grid 专属的弹性单位,它分配的是剩余空间,不是总宽度的百分比。1fr 1fr 1fr 就是三等分——和 33.33% 33.33% 33.33% 的差别在于,有 gap 时 fr 会自动计算剩余空间,百分比不会。
✅ 用 gap 代替 margin: Grid 布局用
gap(或 row-gap/column-gap)来控制间距,不要给每个子元素加 margin。gap 只在项目之间加间距,不会在容器边缘产生多余的空白。
fr 是 Grid 特有的单位,表示"剩余空间的一部分":
▶ 示例
HTML
<style>
.container {
grid-template-columns: 1fr 2fr 1fr; /* 三列,中间是两侧的两倍宽 */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
相当于:总宽度分成 4 份,左右各占 1 份,中间占 2 份。
(4) repeat() 函数
当列或行的模式重复时,用 repeat() 更简洁:
▶ 示例
HTML
<style>
.container {
/* 三列等宽 */
grid-template-columns: 1fr 1fr 1fr;
/* 等价于 */
grid-template-columns: repeat(3, 1fr);
/* 重复模式 */
grid-template-columns: repeat(2, 200px 1fr);
/* 等价于 200px 1fr 200px 1fr */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
(5) 固定尺寸混合
▶ 示例
HTML
<style>
.container {
grid-template-columns: 200px 1fr 200px;
/* 左右固定200px,中间自适应 */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
3. minmax() 函数
设置尺寸的最小值和最大值:
▶ 示例
HTML
<style>
.container {
grid-template-columns: repeat(3, minmax(200px, 1fr));
/* 三列,每列最小200px,最大等分剩余空间 */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
4. auto-fill 和 auto-fit
用于响应式网格,让列数自动适应容器宽度:
▶ 示例
HTML
<style>
.container {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* 每列至少200px,自动填充列数 */
}
.container {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* auto-fit 会折叠空列,auto-fill 保留空列空间 */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
5. 间距属性
(1) gap / row-gap / column-gap
▶ 示例
HTML
<style>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px; /* 行和列间距都是20px */
row-gap: 10px; /* 行间距 */
column-gap: 20px; /* 列间距 */
}
.container-item {
background: #e8f4f8;
border: 1px solid #3498db;
padding: 16px;
margin: 4px;
border-radius: 4px;
text-align: center;
}
</style>
<div class="container">
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
<div class="container-item">Container item</div>
</div>
6. Grid 的自动定位
(1) grid-auto-rows
定义自动生成的行的尺寸(当行数超出定义时):
▶ 示例
HTML
<style>
.container {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto); /* 自动行至少100px高 */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
(2) grid-auto-flow
控制项目的自动排列方式:
▶ 示例
HTML
<style>
.container {
grid-auto-flow: row; /* 默认,先填满行 */
grid-auto-flow: column; /* 先填满列 */
grid-auto-flow: dense; /* 密集排列,填满空隙 */
}
</style>
<div class="container">容器元素,内部包含其他子元素</div>
7. 完整的 Grid 容器示例
▶ 示例
HTML
<style>
.grid-container {
display: grid;
grid-template-columns: 250px 1fr 200px;
grid-template-rows: 80px 1fr 60px;
gap: 10px;
height: 100vh;
}
header {
grid-column: 1 / -1; /* 跨所有列 */
}
footer {
grid-column: 1 / -1; /* 跨所有列 */
}
.grid-container-item {
background: #e8f4f8;
border: 1px solid #3498db;
padding: 16px;
margin: 4px;
border-radius: 4px;
text-align: center;
}
</style>
<div class="grid-container">
<div class="grid-container-item">Grid container item</div>
<div class="grid-container-item">Grid container item</div>
<div class="grid-container-item">Grid container item</div>
</div>
HTML
<div class="grid-container">
<header>头部</header>
<nav>导航/侧栏</nav>
<main>主要内容</main>
<aside>右侧栏</aside>
<footer>底部</footer>
</div>
❓ 常见问题
Q Grid 和 Flexbox 怎么选?
A 一维布局(单行或单列)用 Flexbox,二维布局(同时控制行和列)用 Grid。大多数页面两者配合使用:Grid 做页面整体骨架,Flexbox 做局部排列。一个页面里同时用两者是完全正常的。
Q fr 单位和百分比有什么区别?
A fr 分配的是剩余空间,百分比分配的是总宽度。有 gap 时区别很明显——fr 会自动扣除 gap 后计算比例,百分比不会。比如
1fr 1fr 1fr 在有 gap 的情况下仍然是完美三等分,而 33.33% 33.33% 33.33% 会溢出。Q grid-template-areas 怎么用?
A 用命名区域来定义布局模板,非常直观。比如
grid-template-areas: "header header" "sidebar main" "footer footer";,然后把子元素 grid-area: header 分配进去。改布局时只需调整字符串模板,不用动子元素的定位。8. 实战案例:纯CSS卡片布局
这个案例展示了如何用Grid实现一个响应式卡片布局:
▶ 示例
HTML
📖 仅展示
<style>
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
padding: 20px;
}
.card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
}
.card-image {
width: 100%;
height: 150px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.card-content {
padding: 15px;
}
.card-title {
margin: 0 0 10px 0;
font-size: 18px;
}
.card-desc {
margin: 0;
color: #666;
font-size: 14px;
}
</style>
<div class="card-grid">
<div class="card">
<div class="card-image"></div>
<div class="card-content">
<h3 class="card-title">卡片标题 1</h3>
<p class="card-desc">这是卡片的描述文字,展示了Grid布局的效果。</p>
</div>
</div>
<div class="card">
<div class="card-image"></div>
<div class="card-content">
<h3 class="card-title">卡片标题 2</h3>
<p class="card-desc">这是卡片的描述文字,展示了Grid布局的效果。</p>
</div>
</div>
<div class="card">
<div class="card-image"></div>
<div class="card-content">
<h3 class="card-title">卡片标题 3</h3>
<p class="card-desc">这是卡片的描述文字,展示了Grid布局的效果。</p>
</div>
</div>
</div>
💡 实现原理: 使用
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)) 实现响应式卡片布局。auto-fill 让浏览器自动计算列数,minmax(250px, 1fr) 确保每列最小250px,最大平均分配剩余空间。
📖 小节
- Grid 是一个强大的二维布局系统
- 通过
grid-template-columns和grid-template-rows定义网格结构 - 使用
fr单位分配剩余空间 - 用
repeat()、minmax()创建灵活的网格 gap设置间距,auto-fill和auto-fit配合minmax可以实现真正的响应式网格
📝 作业
基础题
- 创建一个 3×3 的网格容器,每个格子 100px×100px,间距 10px。
- 使用
1fr单位制作一个"左右两栏"布局(左 1fr,右 3fr)。
进阶题
- 使用
repeat(auto-fill, minmax(150px, 1fr))创建一个自动适应宽度的卡片网格——调整浏览器宽度,观察列数自动变化。 - 制作一个"经典三行两列"的页面布局:顶栏(跨两列)、左菜单、右内容、底栏(跨两列)。
挑战题
- 创建一个响应式图片画廊,要求:
- 桌面端:4列
- 平板端:2列
- 手机端:1列
- 使用
auto-fill+minmax实现
- 使用
grid-template-areas实现一个完整的博客页面布局(头部、导航、主内容、侧边栏、底部)。