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>
逻辑代码 59 行(超过 40 行限制,仅展示)
💡 实现原理: 使用 grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)) 实现响应式卡片布局。auto-fill 让浏览器自动计算列数,minmax(250px, 1fr) 确保每列最小250px,最大平均分配剩余空间。

📖 小节

📝 作业

基础题

  1. 创建一个 3×3 的网格容器,每个格子 100px×100px,间距 10px。
  2. 使用 1fr 单位制作一个"左右两栏"布局(左 1fr,右 3fr)。

进阶题

  1. 使用 repeat(auto-fill, minmax(150px, 1fr)) 创建一个自动适应宽度的卡片网格——调整浏览器宽度,观察列数自动变化。
  2. 制作一个"经典三行两列"的页面布局:顶栏(跨两列)、左菜单、右内容、底栏(跨两列)。

挑战题

  1. 创建一个响应式图片画廊,要求:
    • 桌面端:4列
    • 平板端:2列
    • 手机端:1列
    • 使用 auto-fill + minmax 实现
  2. 使用 grid-template-areas 实现一个完整的博客页面布局(头部、导航、主内容、侧边栏、底部)。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏