网格布局

CSS 网格布局 是 Web 的一个二维布局系统。它允许您将内容组织成行和列,并提供许多功能来简化复杂布局的创建。本文将解释您入门网格布局所需了解的所有内容。

先决条件 HTML 基础知识(学习 HTML 简介)以及 CSS 工作原理的概念(学习 CSS 简介样式化盒子)。
目标 了解网格布局的基本概念以及如何使用 CSS 网格实现它。

什么是网格布局?

网格是水平和垂直线段的集合,它们创建一个模式,我们可以根据该模式排列我们的设计元素。它们帮助我们创建布局,使我们的元素不会在页面之间跳动或改变宽度,从而在我们的网站上提供更大的一致性。

网格通常有 **列**、**行**,以及每行和每列之间的间隙。这些间隙通常称为 **槽**。

CSS grid with parts labelled as rows, columns and gutters. Rows are the horizontal segments of the grid and Columns are the vertical segments of the grid. The space between two rows is called as 'row gutter' and the space between 2 columns is called as 'column gutter'.

在 CSS 中创建网格

在确定了设计所需的网格后,您可以使用 CSS 网格布局来创建它。我们首先了解网格布局的基本功能,然后探讨如何为您的项目创建一个简单的网格系统。以下视频提供了使用 CSS 网格的清晰视觉解释

定义网格

让我们借助示例尝试网格布局。下载并在您的文本编辑器和浏览器中打开 起点文件(您也可以 在这里查看)。您将看到一个示例,其中包含一个容器,该容器有一些子项。默认情况下,这些项以普通流显示,导致它们一个接一个地显示。在本课的初始部分,我们将使用此文件来查看其网格的行为。

与定义 Flexbox 的方式类似,您可以通过将 display 属性的值设置为 grid 来定义网格布局。与 Flexbox 一样,display: grid 属性将容器的所有直接子元素转换为网格项。将以下 CSS 添加到您的文件中

css
.container {
  display: grid;
}

与 Flexbox 不同,这些项目不会立即看起来有任何不同。声明 display: grid 会为您提供一个单列网格,因此您的项目将继续像在普通流中一样一个接一个地显示。

要查看更像网格的内容,我们需要向网格中添加一些列。让我们添加三列 200 像素的列。您可以使用任何长度单位或百分比来创建这些列轨道。

css
.container {
  display: grid;
  grid-template-columns: 200px 200px 200px;
}

将第二个声明添加到您的 CSS 规则中,然后重新加载页面。您应该会看到这些项目已重新排列,以便每个网格单元格中都包含一个项目。

使用 fr 单位创建灵活的网格

除了使用长度和百分比创建网格外,我们还可以使用 frfr 单位表示网格容器中可用空间的一部分,用于灵活地调整网格行和列的大小。

将您的轨道列表更改为以下定义,创建三个 1fr 轨道

css
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

您现在拥有了灵活的轨道。fr 单位按比例分配空间。您可以为您的轨道指定不同的正值,如下所示

css
.container {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}

第一个轨道获得 2fr 的可用空间,其他两个轨道获得 1fr,使第一个轨道更大。您可以将 fr 单位与固定长度单位混合使用。在这种情况下,固定轨道的所需空间将首先使用,然后将剩余空间分配给其他轨道。

**注意:**fr 单位分配的是 *可用* 空间,而不是 *所有* 空间。因此,如果您的轨道之一内部有较大的内容,则可共享的空闲空间会减少。

轨道之间的间隙

要创建轨道之间的间隙,我们使用以下属性

css
.container {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 20px;
}

这些间隙可以是任何长度单位或百分比,但不能是 fr 单位。

注意: 用于设置间隙的 gap 属性(column-gaprow-gapgap)以前需要添加 grid- 前缀。规范已更改,但带前缀的版本将作为别名保留。为了安全起见并使代码更健壮,您可以同时添加这两个属性。

css
.container {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  grid-gap: 20px;
  gap: 20px;
}

重复轨道列表

您可以使用 CSS 的 repeat() 函数重复整个或部分轨道列表。将您的轨道列表更改为以下内容:

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

现在您将获得与之前相同的三个 1fr 轨道。传递给 repeat() 函数的第一个值指定您希望重复列表的次数,第二个值是轨道列表,可以是一个或多个您想要重复的轨道。

隐式和显式网格

到目前为止,我们只指定了列轨道,但行会自动创建以容纳内容。此概念突出了显式网格和隐式网格之间的区别。以下是对这两种网格类型之间差异的更多说明:

  • 显式网格 使用 grid-template-columnsgrid-template-rows 创建。
  • 隐式网格 在内容放置在网格外部(例如放置在行中)时,通过绘制额外的网格线扩展定义的显式网格。

默认情况下,在隐式网格中创建的轨道大小为 auto,这通常意味着它们足够大以容纳其内容。如果您希望为隐式网格轨道指定大小,可以使用 grid-auto-rowsgrid-auto-columns 属性。如果您将 grid-auto-rows 的值设置为 100px,您会看到创建的行现在高 100 像素。

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  gap: 20px;
}

minmax() 函数

如果我们在这些轨道中添加的内容高度超过 100 像素,那么我们 100 像素高的轨道将不会非常有用,在这种情况下会导致溢出。最好是让轨道至少高 100 像素,并且在添加更多内容时仍然可以扩展。关于网络的一个相当基本的事实是,您永远无法真正知道某个东西的高度是多少——额外的内容或更大的字体大小会导致尝试在每个维度上都完美像素化的设计出现问题。

minmax() 函数允许我们为轨道设置最小和最大尺寸,例如 minmax(100px, auto)。最小尺寸为 100 像素,但最大尺寸为 auto,它将扩展以容纳更多内容。尝试更改 grid-auto-rows 以使用 minmax 值。

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(100px, auto);
  gap: 20px;
}

如果您添加额外的内容,您会看到轨道会扩展以使其适合。请注意,扩展是沿着行进行的。

尽可能多的列

我们可以结合我们学到的关于轨道列表、重复表示法和 minmax() 的一些知识来创建一个有用的模式。有时,能够要求网格创建尽可能多地适合容器的列会很有帮助。我们通过使用 repeat() 函数设置 grid-template-columns 的值来做到这一点,但不是传入数字,而是传入关键字 auto-fit。对于函数的第二个参数,我们使用 minmax(),其最小值为我们希望具有的最小轨道大小,最大值为 1fr

现在在您的文件中使用以下 CSS 尝试一下:

css
.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  grid-auto-rows: minmax(100px, auto);
  gap: 20px;
}

这是因为网格正在创建尽可能多地适合容器的 200 像素列,然后在所有列之间共享剩余的空间。最大值为 1fr,正如我们已经知道的,它在轨道之间均匀分配空间。

基于行的布局

现在,我们从创建网格转向在网格上放置内容。我们的网格始终具有线条——这些线条从 1 开始编号,并与文档的 书写模式 相关。例如,英语(从左到右书写)中的第 1 列线将在网格的左侧,第 1 行线在顶部,而在阿拉伯语(从右到左书写)中,第 1 列线将在右侧。

为了沿这些线定位项目,我们可以指定项目应放置的网格区域的起始线和结束线。我们可以使用四个属性来执行此操作:

这些属性接受行号作为其值,因此我们可以指定项目应从第 1 行开始,在第 3 行结束,例如。或者,您也可以使用简写属性,让您同时指定起始线和结束线,并用正斜杠 / 分隔。

  • grid-columngrid-column-startgrid-column-end 的简写。
  • grid-rowgrid-row-startgrid-row-end 的简写。

要查看它的实际效果,请下载 基于线的放置起点文件在此处查看。它定义了一个网格和一个简单的文章概述。您可以看到自动放置正在将每个项目放置到网格中的自己的单元格中。

让我们通过使用网格线来安排我们网站的所有元素。将以下规则添加到 CSS 的底部:

css
header {
  grid-column: 1 / 3;
  grid-row: 1;
}

article {
  grid-column: 2;
  grid-row: 2;
}

aside {
  grid-column: 1;
  grid-row: 2;
}

footer {
  grid-column: 1 / 3;
  grid-row: 3;
}

注意: 您还可以使用值 -1 来定位结束列或行线,然后使用负值从末尾向内计数。另请注意,线条始终从显式网格的边缘开始计数,而不是从 隐式网格 开始计数。

使用 grid-template-areas 定位

在网格上排列项目的另一种方法是使用 grid-template-areas 属性并为设计的各个元素命名。

删除上一个示例中的基于线的定位(或重新下载文件以获得新的起点),然后添加以下 CSS。

css
.container {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar content"
    "footer footer";
  grid-template-columns: 1fr 3fr;
  gap: 20px;
}

header {
  grid-area: header;
}

article {
  grid-area: content;
}

aside {
  grid-area: sidebar;
}

footer {
  grid-area: footer;
}

重新加载页面,您将看到您的项目已像以前一样放置,而无需使用任何行号!

grid-template-areas 的规则如下:

  • 您需要填充网格的每个单元格。
  • 要跨越两个单元格,请重复名称。
  • 要留空一个单元格,请使用 .(句点)。
  • 区域必须是矩形的——例如,您不能有一个 L 形区域。
  • 区域不能在不同位置重复。

您可以调整我们的布局,将页脚仅放置在文章下方,并将侧边栏跨越整个页面。这是一种非常好的描述布局的方式,因为仅从 CSS 中查看就可以清楚地知道发生了什么。

嵌套网格和子网格

可以在另一个网格内嵌套网格,从而创建 "子网格"。您可以通过在网格项目上设置 display: grid 属性来实现。

让我们扩展之前的示例,添加一个文章容器,并使用嵌套网格来控制多个文章的布局。虽然我们在嵌套网格中仅使用一列,但我们可以使用 grid-template-rows 属性将行划分为 2:1:1 的比例。这种方法允许我们创建一种布局,其中页面顶部的文章具有较大的显示,而其他文章则具有较小的、类似预览的布局。

css
.articles {
  display: grid;
  grid-template-rows: 2fr 1fr 1fr;
  gap: inherit;
}

article {
  padding: 10px;
  border: 2px solid rgb(79 185 227);
  border-radius: 5px;
}

为了更轻松地处理嵌套网格中的布局,您可以在 grid-template-rowsgrid-template-columns 属性上使用 subgrid。这使您可以利用父网格中定义的轨道。

在以下示例中,我们使用的是 基于线的放置,使嵌套网格能够跨越父网格的多列和多行。我们添加了 subgrid 以继承父网格的列轨道,同时为嵌套网格中的行添加不同的布局。

html
<div class="container">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div id="subgrid">
    <div>Five</div>
    <div>Six</div>
    <div>Seven</div>
    <div>Eight</div>
  </div>
  <div>Nine</div>
  <div>Ten</div>
</div>
css
.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(1, 1fr);
  gap: 10px;
}

#subgrid {
  grid-column: 1 / 4;
  grid-row: 2 / 4;
  display: grid;
  gap: inherit;
  grid-template-columns: subgrid;
  grid-template-rows: 2fr 1fr;
}

网格框架

有许多网格框架可用,提供 12 列或 16 列网格,以帮助您布置内容。好消息是,您可能不需要任何第三方框架来帮助您创建基于网格的布局——网格功能已包含在规范中,并且大多数现代浏览器都支持它。

下载起点文件。它包含一个定义了 12 列网格的容器以及我们在前两个示例中使用的相同标记。现在,我们可以使用基于线的放置将我们的内容放置在 12 列网格上。

css
header {
  grid-column: 1 / 13;
  grid-row: 1;
}

article {
  grid-column: 4 / 13;
  grid-row: 2;
}

aside {
  grid-column: 1 / 4;
  grid-row: 2;
}

footer {
  grid-column: 1 / 13;
  grid-row: 3;
}

如果您使用 Firefox 网格检查器 将网格线叠加在您的设计上,您可以看到我们的 12 列网格是如何工作的。

A 12 column grid overlaid on our design.

测试你的技能!

您已阅读完本文,但您还记得最重要的信息吗?在继续之前,您可以找到一些进一步的测试来验证您是否保留了这些信息——请参阅 测试您的技能:网格

总结

在本概述中,我们介绍了 CSS 网格布局的主要功能。您应该能够在您的设计中开始使用它。要进一步深入了解规范,请阅读我们关于网格布局的指南,这些指南可在下面找到。

另请参阅