网格模板区域

前面的指南 中,我们了解了网格线以及如何将项目定位到这些线上。当您使用 CSS 网格布局时,您始终拥有网格线,这是一种将项目放置到网格上的简单直观的方法。但是,还有一种可选方法可用于在网格上定位项目,您可以单独使用该方法,也可以与基于行的放置方法结合使用。此方法涉及使用命名的模板区域放置项目,我们将了解该方法的工作原理。您很快就会明白为什么我们有时称这种方法为网格布局的 ASCII 艺术方法!

命名网格区域

您已经遇到了 grid-area 属性。此属性可以采用所有四条用于定位网格区域的线的组合作为值。

css
.box1 {
  grid-area: 1 / 1 / 4 / 2;
}

我们在定义所有四条线时,实际上是在通过指定包围该区域的线来定义该区域。

The grid area defined by lines

我们还可以通过为区域命名,然后在 grid-template-areas 属性的值中指定该区域的位置来定义区域。您可以选择您喜欢的区域名称。例如,如果我想创建下面显示的布局,我可以识别四个主要区域。

  • 页眉
  • 页脚
  • 侧边栏
  • 主要内容

An image showing a simple two column layout with header and footer

使用 grid-area 属性,我可以为每个区域分配一个名称。这还不会创建任何布局,但我们现在有了将在布局中使用的命名区域。

css
.header {
  grid-area: hd;
}
.footer {
  grid-area: ft;
}
.content {
  grid-area: main;
}
.sidebar {
  grid-area: sd;
}

定义这些名称后,我便创建布局。这次,我不会通过在项目本身指定行号来放置项目,而是在网格容器上创建整个布局。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-template-areas:
    "hd hd hd hd   hd   hd   hd   hd   hd"
    "sd sd sd main main main main main main"
    "ft ft ft ft   ft   ft   ft   ft   ft";
}
html
<div class="wrapper">
  <div class="header">Header</div>
  <div class="sidebar">Sidebar</div>
  <div class="content">Content</div>
  <div class="footer">Footer</div>
</div>

使用此方法,我们无需在单个网格项目上指定任何内容,一切都在网格容器上完成。我们可以看到布局作为 grid-template-areas 属性的值进行描述。

将网格单元格留空

在此示例中,我们用区域完全填充了网格,没有留下任何空白。但是,使用此布局方法,您可以将网格单元格留空。要留空单元格,请使用句点字符“.”。如果我只想将页脚直接显示在主要内容下方,则需要将侧边栏下方的三个单元格留空。

css
.header {
  grid-area: hd;
}
.footer {
  grid-area: ft;
}
.content {
  grid-area: main;
}
.sidebar {
  grid-area: sd;
}
css
.wrapper {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-template-areas:
    "hd hd hd hd   hd   hd   hd   hd   hd"
    "sd sd sd main main main main main main"
    ".  .  .  ft   ft   ft   ft   ft   ft";
}
html
<div class="wrapper">
  <div class="header">Header</div>
  <div class="sidebar">Sidebar</div>
  <div class="content">Content</div>
  <div class="footer">Footer</div>
</div>

为了使布局更整洁,我可以使用多个“.”字符。只要句点之间至少有一个空格,它就会被计算为一个单元格。对于复杂的布局,将行和列整齐对齐会带来益处。这意味着您实际上可以在 CSS 中看到此布局的外观。

跨越多个单元格

在我们的示例中,每个区域跨越多个网格单元格,我们通过在区域名称之间使用空格来重复该网格区域的名称来实现这一点。您可以添加额外的空格,以便在 grid-template-areas 的值中将列整齐对齐。您可以看到,为了使 hdftmain 对齐,我已执行此操作。

通过链接区域名称创建的区域必须是矩形的,目前无法创建 L 形区域。规范指出,未来的版本可能会提供此功能。但是,您可以像跨列一样轻松地跨行。例如,我们可以通过用 sd 替换 . 来使侧边栏跨越到底部页脚。

css
.header {
  grid-area: hd;
}
.footer {
  grid-area: ft;
}
.content {
  grid-area: main;
}
.sidebar {
  grid-area: sd;
}
css
.wrapper {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  grid-auto-rows: minmax(100px, auto);
  grid-template-areas:
    "hd hd hd hd   hd   hd   hd   hd   hd"
    "sd sd sd main main main main main main"
    "sd sd sd  ft  ft   ft   ft   ft   ft";
}

grid-template-areas 的值必须显示完整的网格,否则它将无效(并且属性将被忽略)。这意味着您必须为每行具有相同数量的单元格,如果单元格为空,则使用句点字符“.”来表示单元格将被留空。如果您的区域不是矩形,您也会创建一个无效的网格。

使用媒体查询重新定义网格

由于我们的布局现在包含在 CSS 的一部分中,因此在不同的断点处进行更改变得非常容易。您可以通过重新定义网格、网格上项目的位置,或同时重新定义两者来完成此操作。

在进行此操作时,在任何媒体查询之外定义区域的名称。这样,无论内容区域放置在网格的哪个位置,它始终被称为main

对于上面的布局,我们可能希望在狭窄的宽度下拥有一个非常简单的布局,定义一个单列网格并将我们的项目堆叠起来。

css
.header {
  grid-area: hd;
}
.footer {
  grid-area: ft;
}
.content {
  grid-area: main;
}
.sidebar {
  grid-area: sd;
}

.wrapper {
  display: grid;
  grid-auto-rows: minmax(100px, auto);
  grid-template-columns: 1fr;
  grid-template-areas:
    "hd"
    "main"
    "sd"
    "ft";
}

然后,我们可以在媒体查询中重新定义该布局,以进入我们的两列布局,如果可用空间更宽,甚至可以将其转换为三列布局。请注意,对于宽布局,我保留我的九列轨道网格,我使用grid-template-areas重新定义项目的放置位置。

css
@media (min-width: 500px) {
  .wrapper {
    grid-template-columns: repeat(9, 1fr);
    grid-template-areas:
      "hd hd hd hd   hd   hd   hd   hd   hd"
      "sd sd sd main main main main main main"
      "sd sd sd  ft  ft   ft   ft   ft   ft";
  }
}
@media (min-width: 700px) {
  .wrapper {
    grid-template-areas:
      "hd hd hd   hd   hd   hd   hd   hd hd"
      "sd sd main main main main main ft ft";
  }
}

使用 grid-template-areas 用于 UI 元素

您在网上找到的许多网格示例都假设您将使用网格进行主页面布局,但是网格对于小元素和大型元素一样有用。使用grid-template-areas特别好,因为在代码中很容易看到元素的外观。

媒体对象示例

作为一个非常简单的示例,我们可以创建一个“媒体对象”。这是一个组件,在一侧留有空间用于图像或其他媒体,另一侧留有空间用于内容。图像可以显示在框的右侧或左侧。

Images showing an example media object design

我们的网格是一个两列轨道网格,图像的列大小为1fr,文本为3fr。如果您想要一个固定宽度图像区域,则可以将图像列设置为像素宽度,并将文本区域分配为1fr。然后,单个1fr列轨道将占据剩余的空间。

我们为图像区域指定了img的网格区域名称,为文本区域指定了content的网格区域名称,然后可以使用grid-template-areas属性来布置它们。

css
* {
  box-sizing: border-box;
}

.media {
  border: 2px solid #f76707;
  border-radius: 5px;
  background-color: #fff4e6;
  max-width: 400px;
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas: "img content";
  margin-bottom: 1em;
}

.media .image {
  grid-area: img;
  background-color: #ffd8a8;
}

.media .text {
  grid-area: content;
  padding: 10px;
}
html
<div class="media">
  <div class="image"></div>
  <div class="text">
    This is a media object example. We can use grid-template-areas to switch
    around the image and text part of the media object.
  </div>
</div>

在框的另一侧显示图像

我们可能希望能够将图像以相反的方式显示在框中。为此,我们重新定义网格以将1fr轨道放在最后,并将grid-template-areas中的值翻转。

css
* {
  box-sizing: border-box;
}

.media {
  border: 2px solid #f76707;
  border-radius: 5px;
  background-color: #fff4e6;
  max-width: 400px;
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas: "img content";
  margin-bottom: 1em;
}

.media.flipped {
  grid-template-columns: 3fr 1fr;
  grid-template-areas: "content img";
}

.media .image {
  grid-area: img;
  background-color: #ffd8a8;
}

.media .text {
  grid-area: content;
  padding: 10px;
}
html
<div class="media flipped">
  <div class="image"></div>
  <div class="text">
    This is a media object example. We can use grid-template-areas to switch
    around the image and text part of the media object.
  </div>
</div>

网格定义简写

在查看了在网格上放置项目的各种方法以及用于定义网格的许多属性之后,现在是时候看一下可用于定义网格和其中许多内容的 CSS 中的一行代码的快捷方式了。

对于其他开发人员,甚至未来的自己来说,这些代码可能很快变得难以阅读。但是它们是规范的一部分,您很可能在示例中或其他开发人员的用例中遇到它们,即使您选择不使用它们。

在使用任何快捷方式之前,值得记住,快捷方式不仅可以在一次设置中设置许多属性,而且还会将您没有或无法在快捷方式中设置的属性重置为其初始值。因此,如果您使用快捷方式,请注意它可能会重置您在其他地方应用的内容。

网格容器的两个快捷方式是显式网格快捷方式grid-template和网格定义快捷方式grid

grid-template

grid-template属性设置以下属性

该属性被称为显式网格快捷方式,因为它正在设置您在定义显式网格时控制的那些内容,而不是那些影响可能创建的任何隐式行或列轨道的那些内容。

以下代码使用grid-template创建了一个布局,该布局与本指南中前面创建的布局相同。

css
.wrapper {
  display: grid;
  grid-template:
    "hd hd hd hd   hd   hd   hd   hd   hd" minmax(100px, auto)
    "sd sd sd main main main main main main" minmax(100px, auto)
    "ft ft ft ft   ft   ft   ft   ft   ft" minmax(100px, auto)
    / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
}

第一个值是我们的grid-template-areas值,但我们还在每行末尾声明行的尺寸。这就是minmax(100px, auto)的作用。

然后在grid-template-areas之后,我们有一个正斜杠,之后是一个显式轨道列出列轨道。

grid

grid快捷方式更进一步,它还设置了隐式网格使用的属性。因此,您将设置

您可以使用与grid-template快捷方式完全相同的语法,只是要注意,这样做时,您将重置该属性设置的其他值。

css
.wrapper {
  display: grid;
  grid:
    "hd hd hd hd   hd   hd   hd   hd   hd" minmax(100px, auto)
    "sd sd sd main main main main main main" minmax(100px, auto)
    "ft ft ft ft   ft   ft   ft   ft   ft" minmax(100px, auto)
    / 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
}

当我们看一下自动放置和grid-auto-flow属性时,我们将在本指南的后面再次回顾此快捷方式提供的其他功能。

如果您已完成这些初始指南,那么现在您应该能够使用基于行的放置或命名区域创建网格布局。花些时间使用网格构建一些常见的布局模式,虽然有很多新术语需要学习,但语法相对简单。当您开发示例时,您可能会提出一些关于我们尚未涵盖的内容的问题和用例。在本指南的其余部分,我们将探讨规范中包含的更多详细信息 - 以便您能够开始使用它创建高级布局。