使用命名网格线布局

在之前的指南中,我们已经了解了如何通过定义网格轨道创建的线来放置项目,以及如何使用命名模板区域来放置项目。在本指南中,我们将了解当我们使用命名线时,这两个方面如何协同工作。命名线非常有用,但一些更让人迷惑的网格语法来自这种命名和轨道大小的组合。一旦你完成了一些示例,它应该变得更清晰,更容易使用。

定义网格时命名行

在使用 grid-template-rowsgrid-template-columns 属性定义网格时,可以为网格中的部分或所有线分配名称。为了演示,我将使用在基于行的放置指南中创建的简单布局。这次,我将使用命名线创建网格。

定义网格时,我在方括号内命名我的线。这些名称可以是任何你喜欢的。我为行和列的容器的开始和结束定义了一个名称。然后将网格的中心块再次定义为 content-startcontent-end,无论对于列还是行,尽管你并不需要为网格上的所有线命名。你可能选择只为布局中的一些关键线命名。

css
.wrapper {
  display: grid;
  grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
  grid-template-rows: [main-start] 100px [content-start] 100px [content-end] 100px [main-end];
}

一旦线有了名称,我们就可以使用名称来放置项目,而不是使用行号。

css
.box1 {
  grid-column-start: main-start;
  grid-row-start: main-start;
  grid-row-end: main-end;
}

.box2 {
  grid-column-start: content-end;
  grid-row-start: main-start;
  grid-row-end: content-end;
}

.box3 {
  grid-column-start: content-start;
  grid-row-start: main-start;
}

.box4 {
  grid-column-start: content-start;
  grid-column-end: main-end;
  grid-row-start: content-end;
}
html
<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
  <div class="box4">Four</div>
</div>

关于基于行的放置的所有其他内容仍然以相同的方式工作,并且可以混合使用命名线和行号。当创建响应式设计时,命名线非常有用,在这种设计中,你需要重新定义网格,而不是在媒体查询中通过更改行号来重新定义内容位置,你可以确保线在你的定义中始终具有相同的名称。

为线指定多个名称

你可能希望为一条线指定多个名称,例如,它可能表示边栏的结束和主区的开始。为此,在方括号内添加名称,并在它们之间用空格隔开 [sidebar-end main-start]。然后,你可以使用这两个名称中的任何一个来引用该线。

从命名行生成隐式网格区域

在命名线时,我提到你可以使用任何你喜欢的名称。该名称是一个 自定义标识符,一个作者定义的名称。在选择名称时,你需要避免可能出现在规范中并引起混淆的词语 - 例如 span。标识符不加引号。

虽然你可以选择任何名称,但如果你在某个区域周围的线后面添加 -start-end,就像我在上面的示例中所做的那样,网格将为你创建一个名为主要名称的命名区域。以上面的示例为例,我为行和列都设置了 content-startcontent-end。这意味着我将获得一个名为 content 的网格区域,如果需要,我可以将内容放置在该区域中。

我使用的是与上面相同的网格定义,但是这次我将把一个项目放置到名为 content 的命名区域中。

css
.wrapper {
  display: grid;
  grid-template-columns: [main-start] 1fr [content-start] 1fr [content-end] 1fr [main-end];
  grid-template-rows: [main-start] 100px [content-start] 100px [content-end] 100px [main-end];
}
.thing {
  grid-area: content;
}
html
<div class="wrapper">
  <div class="thing">I am placed in an area named content.</div>
</div>

我们不需要使用 grid-template-areas 来定义区域在哪里,因为我们的命名线已经为我们创建了一个区域。

从命名区域生成隐式网格线

我们已经了解了命名线如何创建命名区域,反之亦然。命名模板区域会创建你可以用来放置项目的命名线。如果我们以网格模板区域指南中创建的布局为例,我们可以使用区域创建的线来查看它的工作原理。

在这个示例中,我添加了一个额外的 div,它有一个 overlay 类。我们使用 grid-area 属性创建了命名区域,然后使用 grid-template-areas 创建了布局。区域名称是

  • hd
  • ft
  • main
  • sd

这将为我们提供列和行线

  • hd-start
  • hd-end
  • sd-start
  • sd-end
  • main-start
  • main-end
  • ft-start
  • ft-end

您可以在图片中看到命名线,请注意,一些线具有两个名称 - 例如 sd-endmain-start 指的是同一列线。

An image showing the implicit line names created by our grid areas.

使用这些隐式命名线来定位 overlay 与使用我们命名的线来定位项目相同。

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";
}

.header {
  grid-area: hd;
}

.footer {
  grid-area: ft;
}

.content {
  grid-area: main;
}

.sidebar {
  grid-area: sd;
}

.wrapper > div.overlay {
  z-index: 10;
  grid-column: main-start / main-end;
  grid-row: hd-start / ft-end;
  border: 4px solid rgb(92 148 13);
  background-color: rgb(92 148 13 / 40%);
  color: rgb(92 148 13);
  font-size: 150%;
}
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 class="overlay">Overlay</div>
</div>

鉴于我们有这种从命名区域定位创建线和从命名线定位区域的能力,在开始创建网格布局时花点时间规划您的命名策略是值得的。通过选择对您和您的团队有意义的名称,您将帮助每个人更容易使用您创建的布局。

使用 repeat() 为多行使用相同名称

如果您想为网格中的所有线赋予唯一名称,那么您需要长写出轨道定义,而不是使用 repeat 语法,因为您需要在定义轨道时添加方括号中的名称。如果您使用 repeat 语法,您最终将得到多个具有相同名称的线,但这也很有用。

使用 repeat() 的十二列网格

在下一个示例中,我将创建一个具有十二个等宽列的网格。在定义列轨道的 1fr 大小之前,我还定义了一个名为 [col-start] 的线名。这意味着我们将得到一个网格,该网格在宽度为 1fr 的列之前有 12 个名为 col-start 的列线。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(12, [col-start] 1fr);
}

创建网格后,您可以将项目放置到其中。由于我们有多个名为 col-start 的线,如果您将项目放置到从线 col-start 开始的位置,网格将使用第一个名为 col-start 的线,在本例中是左边的线。要定位另一条线,请使用名称加该线的数字。要将我们的项目从第一个名为 col-start 的线放置到第 5 个线,我们可以使用

css
.item1 {
  grid-column: col-start / col-start 5;
}

您也可以在这里使用 span 关键字。我的下一个项目将从第 7 个名为 col-start 的线开始,并跨越 3 个线。

css
.item2 {
  grid-column: col-start 7 / span 3;
}
html
<div class="wrapper">
  <div class="item1">I am placed from col-start line 1 to col-start 5</div>
  <div class="item2">I am placed from col-start line 7 spanning 3 lines</div>
</div>

如果您在 Firefox 网格高亮显示器中查看此布局,您将看到如何显示列线以及如何将项目放置在这些线旁边。

The 12 column grid with items placed. The grid highlighter shows the position of the lines.

使用轨道列表定义命名线

repeat 语法也可以接受轨道列表,它不只是重复单个轨道大小。下面的代码将创建一个具有八个轨道的网格,其中一个名为 col1-start 的更窄的 1fr 宽度列,后面是一个名为 col2-start 的更宽的 3fr 列。

css
.wrapper {
  grid-template-columns: repeat(4, [col1-start] 1fr [col2-start] 3fr);
}

如果您的重复语法将两条线并排放置,那么它们将被合并,并创建与在非重复轨道定义中为线赋予多个名称相同的结果。以下定义创建了四个 1fr 轨道,每个轨道都有一个起始线和结束线。

css
.wrapper {
  grid-template-columns: repeat(4, [col-start] 1fr [col-end]);
}

如果我们不使用 repeat 符号写出此定义,它将如下所示。

css
.wrapper {
  grid-template-columns: [col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end col-start] 1fr [col-end];
}

如果您使用了轨道列表,那么您可以使用 span 关键字不仅跨越一定数量的线,还可以跨越一定数量的特定名称的线。

css
.wrapper {
  display: grid;
  grid-template-columns: repeat(6, [col1-start] 1fr [col2-start] 3fr);
}

.item1 {
  grid-column: col1-start / col2-start 2;
}

.item2 {
  grid-row: 2;
  grid-column: col1-start 2 / span 2 col1-start;
}
html
<div class="wrapper">
  <div class="item1">
    I am placed from col1-start line 1 to col2-start line 2
  </div>
  <div class="item2">
    I am placed from col1-start line 2 spanning 2 lines named col1-start
  </div>
</div>

十二列网格框架

在过去的三份指南中,您已经发现有很多不同的方法可以使用网格放置项目。这在最初看起来可能有点过于复杂,但请记住,您不必使用所有方法。在实践中,我发现对于简单的布局,使用命名模板区域效果很好,它提供了布局外观的良好视觉表示,然后可以轻松地在网格上移动项目。

如果使用严格的多列布局,例如本指南最后部分中命名线的演示效果很好。如果您考虑网格系统,例如在 Foundation 或 Bootstrap 等框架中找到的网格系统,这些网格系统基于 12 列网格。然后,框架导入代码以执行所有计算,以确保列加起来为 100%。对于网格布局,我们唯一的“框架”代码是

css
.wrapper {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(12, [col-start] 1fr);
}

然后,我们可以使用该框架来布局我们的页面。例如,要创建一个带有标题和页脚的三列布局,我可能会有以下标记。

html
<div class="wrapper">
  <header class="main-header">I am the header</header>
  <aside class="side1">I am sidebar 1</aside>
  <article class="content">I am the main article</article>
  <aside class="side2">I am sidebar 2</aside>
  <footer class="main-footer">I am the footer</footer>
</div>

然后,我可以将它放置在网格布局框架中,如下所示。

css
.main-header,
.main-footer {
  grid-column: col-start / span 12;
}

.side1 {
  grid-column: col-start / span 3;
  grid-row: 2;
}

.content {
  grid-column: col-start 4 / span 6;
  grid-row: 2;
}

.side2 {
  grid-column: col-start 10 / span 3;
  grid-row: 2;
}

网格高亮显示器再次对我们很有帮助,它可以显示我们放置项目的网格的工作方式。

The layout with the grid highlighted.

这就够了。我无需进行任何计算,网格会自动删除 10 像素的边距轨道,然后将空间分配给 1fr 列轨道。随着您开始构建自己的布局,您会发现语法变得更加熟悉,您会选择最适合您和您喜欢构建的项目类型的方式。尝试使用这些不同的方法构建一些常见模式,您很快就会找到最有效的工作方式。然后,在下一份指南中,我们将看看网格如何为我们定位项目,而无需我们使用任何放置属性!