Grid

网格简介

使用 CSS,你可以优雅地在网页上布局元素。如何实现最佳布局并没有一个统一的答案------这取决于你要展示的内容,不同的技术可能都有不错的效果。Box Model(盒模型)、Display(显示)和 Positioning(定位)已经介绍了一些可能的布局方式。

在本课中,我们将介绍一个强大的工具 ------ CSS Grid(网格布局) 。Grid 可以用来布局整个网页。与主要用于一维布局 的 Flexbox 不同,CSS Grid 更适用于二维布局,它提供了许多工具,可以让你在行与列之间对元素进行对齐和移动。

在本课结束时,你将学会使用以下属性来创建网格布局:

  • grid-template-columns

  • grid-template-rows

  • grid-template

  • grid-template-area

  • row-gap / column-gap / gap

  • grid-row-start

  • grid-row-end

  • grid-column-start

  • grid-column-end

  • grid-area

创建 Grid

要设置一个 grid,你需要包含两部分:

  • 网格容器(grid container)
  • 网格项(grid items)

网格容器 是一个父元素,里面包含多个子元素(网格项),它负责整个网格的布局样式和位置控制。

也就是说,只要你把某个元素的 display 设置为 gridinline-grid,这个元素就变成了可以使用 CSS Grid 布局的"容器"了。

创建列

默认情况下,Grid 网格只有一列 。如果你开始往里面添加项目,每个项目都会被放在新的一行上 ------ 这样看起来根本不像一个"网格"!

要改变这种情况,我们需要明确指定网格的行数和列数

如何定义列

我们可以使用 CSS 属性 grid-template-columns 来定义。下面是一个使用示例:

css 复制代码
.grid {
  display: grid;
  width: 500px;
  grid-template-columns: 100px 200px;
}

这个属性做了两件事:

  1. 定义了网格的列数 ------ 这里是 2 列。
  2. 设置了每一列的宽度 ------ 第一列宽 100 像素,第二列宽 200 像素。

使用百分比定义列宽

你还可以用百分比来设置列宽,这个百分比是相对于整个网格宽度而言的:

css 复制代码
.grid {
  display: grid;
  width: 1000px;
  grid-template-columns: 20% 50%;
}

这个例子中,网格的总宽度是 1000 像素:

  • 第一列占 20%,所以宽度是 200px
  • 第二列占 50%,所以宽度是 500px

混合使用单位(像素 + 百分比)

你也可以混合使用不同的单位,比如:

css 复制代码
.grid {
  display: grid;
  width: 100px;
  grid-template-columns: 20px 40% 60px;
}

这个例子里,有三列,宽度分别是:

  • 20px
  • 40%(即 40px)
  • 60px

总宽度是 120px ,但网格宽度只有 100px。这会导致列超出容器宽度 ,可能会把页面上其他元素给挤出去!

在后续的课程中,我们会讲到如何**避免内容溢出(overflow)**的问题。

创建行

我们已经学过如何明确地定义网格的列数。现在我们要来学习如何使用属性 grid-template-rows指定网格的行数和每一行的高度

grid-template-rows 属性

这个属性的用法和 grid-template-columns 非常相似。来看下面这段代码,两个属性一起使用的示例:

css 复制代码
.grid {
  display: grid;
  width: 1000px;
  height: 500px;
  grid-template-columns: 100px 200px;
  grid-template-rows: 10% 20% 600px;
}

这个网格有 两列三行
grid-template-rows 定义了:

  • 有几行
  • 每一行的高度

在这个例子中:

  • 第一行是 10% 的高度 → 50 像素(500 的 10%)
  • 第二行是 20% 的高度 → 100 像素
  • 第三行是固定的 → 600 像素

使用百分比时要记住:

  • grid-template-rows 的百分比是基于 网格容器的高度
  • grid-template-columns 的百分比是基于 网格容器的宽度

网格模板

我们可以使用简写属性 grid-template 来代替之前的两个属性(grid-template-rowsgrid-template-columns)。看看下面的代码,你会发现那两个属性已经不见踪影了:

css 复制代码
.grid {
  display: grid;
  width: 1000px;
  height: 500px;
  grid-template: 200px 300px / 20% 10% 70%;
}

怎么理解这段写法?

  • 斜杠 / 前面 的值表示:每一行的高度
  • 斜杠 / 后面 的值表示:每一列的宽度

所以这段代码的含义是:

  • 创建了 2 行 ,高度分别是 200px300px

  • 创建了 3 列,宽度分别是:

    • 20%(相对于容器宽度)
    • 10%
    • 70%

百分比的规则依然适用:

  • 行高的百分比是相对于网格容器的高度
  • 列宽的百分比是相对于网格容器的宽度

Fraction

你也许已经熟悉了几种响应式单位,比如 %(百分比)、emrem

CSS Grid 引入了一种新的相对尺寸单位fr,代表 fraction(分数)

什么是 fr 单位?

使用 fr 单位时,我们可以把列或行的尺寸定义为整个网格可用空间的一部分

这是专门为 CSS Grid 设计的单位。

使用 fr 有个好处:可以轻松避免内容溢出网格边界。

css 复制代码
.grid {
  display: grid;
  width: 1000px;
  height: 400px;
  grid-template: 2fr 1fr 1fr / 1fr 3fr 1fr;
}

这段代码表示:

  • 网格有 3 行3 列

  • 总高度是 400px

    • 第 1 行占 2 份 → 200px
    • 第 2 行占 1 份 → 100px
    • 第 3 行占 1 份 → 100px
  • 总宽度是 1000px

    • 第 1 列占 1/5(1fr)→ 200px
    • 第 2 列占 3/5(3fr)→ 600px
    • 第 3 列占 1/5(1fr)→ 200px

fr 和其他单位混合使用

你也可以将 fr 与其他单位(如 px)一起使用:

css 复制代码
.grid {
  display: grid;
  width: 100px;
  grid-template-columns: 1fr 60px 1fr;
}
  • 第二列固定为 60px

  • 网格总宽度是 100px

  • 剩下的空间是 40px ,由两侧各自的 1fr 平分

    → 第 1 列和第 3 列各占 20px

fr% 的核心区别

特性 % 百分比 fr 分数单位
参照对象 父元素的总宽度/高度 网格容器中剩余空间
用途 指定固定比例的空间 用于按比例划分剩余空间
适用场景 对内容块直接按比例控制大小 在网格中更方便、灵活地创建分栏/分行布局
混合行为 不太适合与固定单位混合 px 等固定单位混合效果非常直观

举例:

css 复制代码
.grid {
  display: grid;
  width: 1000px;
  grid-template-columns: 200px 1fr 1fr;
}
  • 第一列是固定 200px

  • 剩下的空间(800px)被 1fr 1fr 均分,每列 400px

    这就是 fr 的强大之处:自动计算剩余空间,并按比例分配

repeat函数

用于定义 Grid 中行数和列数 的属性(如 grid-template-columnsgrid-template-rows)可以接收一个函数作为取值,repeat() 就是其中专门为 CSS Grid 创建的函数之一。

css 复制代码
.grid {
  display: grid;
  width: 300px;
  grid-template-columns: repeat(3, 100px);
}

repeat(3, 100px) 的意思是:

  • 创建 3 个列,每个都是 100 像素宽
    等价于手动写:
css 复制代码
grid-template-columns: 100px 100px 100px;

repeat()fr 配合使用

repeat() 在配合 fr 使用时尤其强大:

css 复制代码
grid-template-columns: repeat(5, 1fr);

这表示创建 5 列,每列占用相同的空间。非常适合需要等分布局的场景。

repeat() 的高级用法:传多个值

repeat() 的第二个参数也可以包含多个值:

css 复制代码
grid-template-columns: repeat(2, 20px 50px);

这个例子表示:

  • 重复两次 20px 50px
  • 实际上会创建 4 列,宽度依次为:20px, 50px, 20px, 50px

minmax 函数

到目前为止,我们创建的所有 网格(grid) 都是固定尺寸的。比如示例中的网格宽 400 像素,高 500 像素。但有时候,你可能希望网格根据浏览器窗口大小自动调整大小。

在这种情况下,你可能希望某些行或列的大小不要太小或太大

比如说,你有一张宽 100 像素的图片放在某一列里,你可能就不希望这列变得比图片还窄!

这时候,minmax() 函数就能派上用场。

css 复制代码
.grid {
  display: grid;
  grid-template-columns: 100px minmax(100px, 500px) 100px;
}

解释如下:

  • 第一列:始终是 100 像素
  • 第三列:也是始终 100 像素
  • 第二列:宽度会随网格大小自动变化 ,但始终保持在 100px 到 500px 之间

也就是说,不管页面怎么变大变小,第二列都不会太窄也不会太宽,非常适合用在响应式布局中。

Grid Gap

到目前为止,我们创建的所有网格项目之间都没有任何空隙

可以使用 CSS 属性 row-gapcolumn-gap 来在网格的每一行和每一列之间添加空白间距。

css 复制代码
.grid {
  display: grid;
  width: 320px;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 10px;
}

这段代码的含义是:

  • 网格宽度为 320px。
  • 使用 repeat(3, 1fr) 创建 3 列,每列宽度相同。
  • 使用 column-gap: 10px;,在列与列之间添加了 10 像素的间距。

注意:grid gap 不会在网格的起始和末尾添加间距 ,只会在项与项之间添加。

在这个例子中:

  • 有 3 列,两个 10px 的间距,共占用了 20 像素;
  • 所以剩下的可用空间是 320px - 20px = 300px
  • 每列都是 1fr,所以平分这 300 像素,即每列宽度为 100px

gap 简写属性

我们也可以使用简写属性 gap 一次性设置行间距和列间距:

css 复制代码
.grid {
  display: grid;
  width: 320px;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px 10px;
}

这个例子会:

  • 设置行与行之间的距离为 20px
  • 设置列与列之间的距离为 10px

小提示:

  • gap: 行距 列距;
  • 不像 grid-template 属性,不需要 / 分隔
  • 如果只写一个值,如 gap: 10px;,表示行距和列距都为 10px

你可能在旧代码中见过这些写法:

  • grid-row-gap
  • grid-column-gap
  • grid-gap

这些属性已经被废弃(deprecated) ,建议现在都统一使用 gaprow-gapcolumn-gap

Multiple Row Items

使用 CSS 属性 grid-row-startgrid-row-end,我们可以让单个网格项目占据多行。记住,此时我们不再是给外层的网格容器添加 CSS,而是对 网格中的子元素 进行样式设置!

css 复制代码
.item {
  grid-row-start: 1;
  grid-row-end: 3;
}

在这个例子中,类名为 .item 的 HTML 元素将在网格中占据两行,即第 1 行和第 2 行。

grid-row-startgrid-row-end 接受的值是 网格线(grid lines)

行网格线列网格线 从 1 开始编号,最后一个编号会比网格中的行数或列数多 1。

举例来说:

  • 如果一个网格有 5 行,那么行网格线的编号是从 1 到 6。
  • 如果有 8 行,行网格线范围是 1 到 9。
  • grid-row-start 的值表示你希望该项目 从哪一行开始
  • grid-row-end 的值应该是你希望它结束的那一行 再加 1

例如:如果你希望一个元素跨越第 2、3 和 4 行,它的设置应为:

css 复制代码
grid-row-start: 2;
grid-row-end: 5;

另外,grid-row-start 的值也可以大于 grid-row-end,两个属性还都可以接受负值。

css 复制代码
  grid-row-start: 5;
  grid-row-end: 7;

效果:

Grid Row

我们可以使用 grid-row 属性作为 grid-row-startgrid-row-end 的简写。下面这两个代码块的效果是一样的:

css 复制代码
.item {
  grid-row-start: 4;
  grid-row-end: 6;
}

等同于:

css 复制代码
.item {
  grid-row: 4 / 6;
}

这段代码的写法与 grid-template 作为 grid-template-rowsgrid-template-columns 的简写方式类似。

在这里,起始行的位置写在 / 的前面,结束行的位置写在 / 的后面。再次强调,结束行是"排除"的,也就是说这个网格项会占据第 4 行和第 5 行。

当一个项目使用这些属性跨越多行或多列时,如果网格中设置了 gap 间距,它也会被计算在内。

例如:如果一个项目跨越两个高度为 100 像素的行,并且行之间有一个 10 像素的间距,那么该项目的总高度将是:

100 + 10 + 100 = 210 像素

Grid Column

前面提到的三个属性同样也适用于列:

  • grid-column-start
  • grid-column-end
  • grid-column

它们的作用与行相关的属性完全一样,允许一个网格项跨越多个列。

在使用这些属性时,我们可以使用关键字 span,通过相对于另一端的位置来指定开始或结束的列或行。请看下面代码中 span 的用法:

css 复制代码
.item {
  grid-column: 4 / span 2;
}

这段代码的意思是,让 .item 元素从第 4 列开始,占据 2 列的宽度。所以,它会覆盖第 4 和第 5 列。它与下面这些写法效果相同:

css 复制代码
.item {
  grid-column: 4 / 6;
}
css 复制代码
.item {
  grid-column-start: 4;
  grid-column-end: span 2;
}
css 复制代码
.item {
  grid-column-start: span 2;
  grid-column-end: 6;
}

span 是一个非常实用的关键字,它告诉 CSS 网格布局让某个元素"跨越"一定数量的网格单元格(而不是指定它在哪个网格线开始或结束) 如果你清楚地知道元素从哪里开始 ,以及它需要占多少列 ,那就用 span 吧!

Grid Area

我们已经学会了使用 grid-rowgrid-column 作为简写来代替 grid-row-startgrid-row-end 等属性。而现在,我们可以通过 grid-area 属性进一步简化写法。这个属性可以同时设置元素在网格中开始和结束的位置 ,包括行和列

css 复制代码
.item {
  grid-area: 2 / 3 / 4 / span 5;
}

grid-area 接受四个用斜杠( / )分隔的值,顺序非常重要! 它的顺序如下:

  1. grid-row-start(行开始线)
  2. grid-column-start(列开始线)
  3. grid-row-end(行结束线)
  4. grid-column-end(列结束线)

在上面的例子中:

css 复制代码
.item {
  grid-area: 2 / 3 / 4 / span 5;
}

意思是:

  • 第 2 行线 开始(grid-row-start: 2
  • 第 3 列线 开始(grid-column-start: 3
  • 结束于 第 4 行线 (不包含 4,覆盖的是第 2 和第 3 行)(grid-row-end: 4
  • 列方向上使用了 span 5,意味着这个元素会横跨 5 个列单元格 ,也就是第 3、4、5、6、7 列(grid-column-end: span 5

使用 grid-area 是一种简单直观的方法,可以让你精确控制元素在网格中的位置和占据的大小,代码也更加整洁。

到目前为止,我们已经学习了很多种操作网格及其内部元素的方法,从而创建出丰富多样的布局。

  • grid-template-columns:定义网格中列的数量和宽度
  • grid-template-rows:定义网格中行的数量和高度
  • grid-template:是 grid-template-columnsgrid-template-rows简写
  • row-gap:在网格的行之间添加空白间距
  • column-gap:在网格的列之间添加空白间距
  • gap:是 row-gapcolumn-gap简写,可以同时设置行距和列距
  • grid-row-startgrid-row-end:让元素跨越多个行
  • grid-column-startgrid-column-end:让元素跨越多个列
  • grid-area:是 grid-row-startgrid-column-startgrid-row-endgrid-column-end简写,可以一行代码同时设置这四个属性

你已经掌握了如何设置网格,以及如何填充和定位网格中的元素。这是你 CSS 布局工具箱中又增加的一项新技能!

相关推荐
前端开发张小七5 分钟前
13.Python Socket服务端开发指南
前端·python
前端开发张小七7 分钟前
14.Python Socket客户端开发指南
前端·python
ElasticPDF-新国产PDF编辑器22 分钟前
Vue 项目 PDF 批注插件库在线版 API 示例教程
前端·vue.js·pdf
拉不动的猪29 分钟前
react基础2
前端·javascript·面试
kovlistudio29 分钟前
红宝书第二十九讲:详解编辑器和IDE:VS Code与WebStorm
开发语言·前端·javascript·ide·学习·编辑器·webstorm
拉不动的猪31 分钟前
react基础1
前端·javascript·面试
鱼樱前端1 小时前
Vite 工程化深度解析与最佳实践
前端·javascript
鱼樱前端1 小时前
Webpack 在前端工程化中的核心应用解析-构建老大
前端·javascript
Moment1 小时前
多人协同编辑算法 —— CRDT 算法 🐂🐂🐂
前端·javascript·面试
小付同学呀1 小时前
前端快速入门学习4——CSS盒子模型、浮动、定位
前端·css·学习