网格简介
使用 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
设置为 grid
或 inline-grid
,这个元素就变成了可以使用 CSS Grid 布局的"容器"了。
创建列
默认情况下,Grid 网格只有一列 。如果你开始往里面添加项目,每个项目都会被放在新的一行上 ------ 这样看起来根本不像一个"网格"!
要改变这种情况,我们需要明确指定网格的行数和列数。
如何定义列
我们可以使用 CSS 属性 grid-template-columns
来定义。下面是一个使用示例:
css
.grid {
display: grid;
width: 500px;
grid-template-columns: 100px 200px;
}
这个属性做了两件事:
- 定义了网格的列数 ------ 这里是 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-rows
和 grid-template-columns
)。看看下面的代码,你会发现那两个属性已经不见踪影了:
css
.grid {
display: grid;
width: 1000px;
height: 500px;
grid-template: 200px 300px / 20% 10% 70%;
}
怎么理解这段写法?
- 斜杠
/
前面 的值表示:每一行的高度 - 斜杠
/
后面 的值表示:每一列的宽度
所以这段代码的含义是:
-
创建了 2 行 ,高度分别是
200px
和300px
-
创建了 3 列,宽度分别是:
- 20%(相对于容器宽度)
- 10%
- 70%
百分比的规则依然适用:
- 行高的百分比是相对于网格容器的高度
- 列宽的百分比是相对于网格容器的宽度
Fraction
你也许已经熟悉了几种响应式单位,比如 %
(百分比)、em
和 rem
。
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-columns
和 grid-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-gap
和 column-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) ,建议现在都统一使用 gap
、row-gap
和 column-gap
。
Multiple Row Items
使用 CSS 属性 grid-row-start
和 grid-row-end
,我们可以让单个网格项目占据多行。记住,此时我们不再是给外层的网格容器添加 CSS,而是对 网格中的子元素 进行样式设置!
css
.item {
grid-row-start: 1;
grid-row-end: 3;
}
在这个例子中,类名为 .item
的 HTML 元素将在网格中占据两行,即第 1 行和第 2 行。
grid-row-start
和 grid-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-start
和 grid-row-end
的简写。下面这两个代码块的效果是一样的:
css
.item {
grid-row-start: 4;
grid-row-end: 6;
}
等同于:
css
.item {
grid-row: 4 / 6;
}
这段代码的写法与 grid-template
作为 grid-template-rows
和 grid-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-row
和 grid-column
作为简写来代替 grid-row-start
和 grid-row-end
等属性。而现在,我们可以通过 grid-area
属性进一步简化写法。这个属性可以同时设置元素在网格中开始和结束的位置 ,包括行和列。
css
.item {
grid-area: 2 / 3 / 4 / span 5;
}
grid-area
接受四个用斜杠( /
)分隔的值,顺序非常重要! 它的顺序如下:
grid-row-start
(行开始线)grid-column-start
(列开始线)grid-row-end
(行结束线)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-columns
和grid-template-rows
的简写row-gap
:在网格的行之间添加空白间距column-gap
:在网格的列之间添加空白间距gap
:是row-gap
和column-gap
的简写,可以同时设置行距和列距grid-row-start
和grid-row-end
:让元素跨越多个行grid-column-start
和grid-column-end
:让元素跨越多个列grid-area
:是grid-row-start
、grid-column-start
、grid-row-end
和grid-column-end
的简写,可以一行代码同时设置这四个属性
你已经掌握了如何设置网格,以及如何填充和定位网格中的元素。这是你 CSS 布局工具箱中又增加的一项新技能!