使用基于行的布局的网格布局
在介绍网格布局基本概念的文章中,我们开始了解如何使用行号在网格上定位项目。在本文中,我们将全面探讨规范中这个基本功能的工作原理。
从使用编号行开始你的网格探索是最合乎逻辑的,因为当你使用网格布局时,你总是拥有编号行。这些行是为列和行编号的,并从 1 开始索引。请注意,网格是根据文档的书写模式索引的。在英语等从左到右的语言中,第 1 行位于网格的左侧。如果你正在使用阿拉伯语等从右到左的语言,那么第 1 行将位于网格的最右侧。我们将在以后的指南中详细了解书写模式和网格之间的交互作用。
基本示例
作为一个非常简单的例子,我们可以拿一个具有 3 列轨道和 3 行轨道的网格。这让我们在每个维度上有 4 行。
在我们的网格容器内,我们有四个子元素。如果我们不以任何方式将它们放置到网格上,它们将根据自动放置规则进行布局,每个单元格中放置一个项目。如果你使用Firefox 网格高亮器,你就可以看到网格是如何定义列和行的。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
}
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
按行号定位项目
我们可以使用基于行的放置来控制这些项目在网格上的位置。我们希望第一个项目从网格的最左侧开始,并跨越一个单列轨道。它也应该从第一行开始,位于网格的顶部,并跨越到第四行。
.box1 {
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 1;
grid-row-end: 4;
}
当你放置一些项目时,网格上的其他项目将继续使用自动放置规则进行布局。我们将在以后的指南中仔细研究它们是如何工作的,但你可以看到,当你工作时,网格将未放置的项目布局到网格的空单元格中。
通过分别处理每个项目,我们可以放置所有四个跨越行和列轨道的项目。请注意,如果我们希望可以留下空单元格。网格布局非常棒的一点是,它能够在我们的设计中留出空白,而无需使用边距将项目推开,以防止浮动项目上升到我们留下的空白区域。
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 1;
grid-row-end: 4;
}
.box2 {
grid-column-start: 3;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
}
.box3 {
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}
.box4 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 3;
grid-row-end: 4;
}
grid-column
和 grid-row
简写
我们在这里有相当多的代码来放置每个项目。毫不奇怪,有一个简写形式。grid-column-start
和 grid-column-end
属性可以组合到 grid-column
中,grid-row-start
和 grid-row-end
可以组合到 grid-row
中。
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column: 1 / 2;
grid-row: 1 / 4;
}
.box2 {
grid-column: 3 / 4;
grid-row: 1 / 3;
}
.box3 {
grid-column: 2 / 3;
grid-row: 1 / 2;
}
.box4 {
grid-column: 2 / 4;
grid-row: 3 / 4;
}
默认跨度
在上面的示例中,我们指定了每个结束行和列行,以便演示属性,但在实践中,如果项目只跨越一个轨道,你可以省略 grid-column-end
或 grid-row-end
值。网格默认跨越一个轨道。
使用长手放置时的默认跨度
这意味着我们的初始长手示例将如下所示
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column-start: 1;
grid-row-start: 1;
grid-row-end: 4;
}
.box2 {
grid-column-start: 3;
grid-row-start: 1;
grid-row-end: 3;
}
.box3 {
grid-column-start: 2;
grid-row-start: 1;
}
.box4 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 3;
}
使用简写放置时的默认跨度
我们的简写形式将如下面的代码所示,没有正斜杠,并且没有第二个值为仅跨越一个轨道的项目。
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column: 1;
grid-row: 1 / 4;
}
.box2 {
grid-column: 3;
grid-row: 1 / 3;
}
.box3 {
grid-column: 2;
grid-row: 1;
}
.box4 {
grid-column: 2 / 4;
grid-row: 3;
}
grid-area
属性
我们可以更进一步,使用单个属性 grid-area
来定义每个区域。grid-area
的值顺序如下。
- grid-row-start
- grid-column-start
- grid-row-end
- grid-column-end
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-area: 1 / 1 / 4 / 2;
}
.box2 {
grid-area: 1 / 3 / 3 / 4;
}
.box3 {
grid-area: 1 / 2 / 2 / 3;
}
.box4 {
grid-area: 3 / 2 / 4 / 4;
}
grid-area
的值顺序可能看起来有点奇怪,它与我们指定边距和填充等简写形式的方向相反。可能有助于意识到这是因为网格使用 CSS 书写模式规范中定义的流相关方向。我们将在以后的文章中探讨网格如何与书写模式一起工作,但我们有四个流相关方向的概念
- block-start
- block-end
- inline-start
- inline-end
我们使用英语,一种从左到右的语言。我们的块开始是网格容器的顶行线,块结束是容器的最后一行线。我们的内联开始是左边的列线,因为内联开始始终是文本在当前书写模式下开始书写的位置,内联结束是我们网格的最后一列线。
当我们使用grid-area
属性指定网格区域时,我们首先定义两个开始线block-start
和inline-start
,然后定义两个结束线block-end
和inline-end
。这乍一看似乎很不寻常,因为我们习惯了顶部、右侧、底部和左侧的物理属性,但如果你开始将网站视为书写模式的多方向性,就会更有意义。
倒数
我们也可以从网格的块和内联结束处倒数,对于英语来说,那是右边的列线和最后一行线。这些线可以被视为-1
,你可以从那里倒数——因此倒数第二行是-2
。值得注意的是,最后一行是显式网格的最后一行,即由grid-template-columns
和grid-template-rows
定义的网格,并且不考虑在该网格之外隐式网格中添加的任何行或列。
在下一个示例中,我们在放置项目时从网格的右侧和底部开始,翻转了我们正在使用的布局。
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column-start: -1;
grid-column-end: -2;
grid-row-start: -1;
grid-row-end: -4;
}
.box2 {
grid-column-start: -3;
grid-column-end: -4;
grid-row-start: -1;
grid-row-end: -3;
}
.box3 {
grid-column-start: -2;
grid-column-end: -3;
grid-row-start: -1;
grid-row-end: -2;
}
.box4 {
grid-column-start: -2;
grid-column-end: -4;
grid-row-start: -3;
grid-row-end: -4;
}
将项目跨越网格拉伸
能够解决网格的开始和结束线很有用,因为你可以使用以下方法将项目跨越整个网格拉伸
.item {
grid-column: 1 / -1;
}
间隙或巷道
CSS 网格规范包括使用 column-gap
和 row-gap
属性在列和行轨道之间添加间距的能力。它们指定了一个间距,其行为类似于多列布局中的 column-gap
属性。
注意:当网格第一次在浏览器中发布时,column-gap
、row-gap
和 gap
属性带有grid-
前缀,分别为grid-column-gap
、grid-row-gap
和 grid-gap
。
浏览器正在更新其渲染引擎以删除此前缀,但是有前缀的版本将被保留为别名,使其安全使用。
间距只出现在网格轨道之间,它们不会在容器的顶部和底部、左侧或右侧添加空间。我们可以通过在网格容器上使用这些属性,将间距添加到我们之前的示例中。
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column: 1;
grid-row: 1 / 4;
}
.box2 {
grid-column: 3;
grid-row: 1 / 3;
}
.box3 {
grid-column: 2;
grid-row: 1;
}
.box4 {
grid-column: 2 / 4;
grid-row: 3;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
column-gap: 20px;
row-gap: 1em;
}
间距速记
这两个属性也可以用速记 gap
表示。如果只为gap
提供一个值,它将应用于列和行间距。如果指定两个值,第一个用于row-gap
,第二个用于column-gap
。
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 1em 20px;
}
就项目的基于线的定位而言,间距的作用就像线获得了额外的宽度一样。从该线开始的任何内容都将在间距之后开始,你无法解决间距或将任何内容放置到其中。如果你想要更像常规轨道一样起作用的间距,当然可以定义一个轨道来专门用于此目的。
使用 span
关键字
除了通过数字指定开始和结束线之外,你还可以指定一个开始线,然后指定你希望区域跨越的轨道数。
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
</div>
.box1 {
grid-column: 1;
grid-row: 1 / span 3;
}
.box2 {
grid-column: 3;
grid-row: 1 / span 2;
}
.box3 {
grid-column: 2;
grid-row: 1;
}
.box4 {
grid-column: 2 / span 2;
grid-row: 3;
}
你也可以在grid-row-start
/grid-row-end
和grid-column-start/grid-column-end
的值中使用span
关键字。以下两个示例将创建相同的网格区域。在第一个示例中,我们设置开始行线,然后设置结束线,我们指定希望区域覆盖 3 个轨道。区域将从第 1 行开始,从第 1 行结束 3 行;也就是说,区域将在第 4 行结束。
.box1 {
grid-column-start: 1;
grid-row-start: 1;
grid-row-end: span 3;
}
在第二个示例中,我们指定我们希望项目结束的结束行线,然后将开始行线设置为span 3
。这意味着项目需要从指定的行线向上跨越。区域将从第 4 行开始,跨越 3 行到第 1 行。
.box1 {
grid-column-start: 1;
grid-row-start: span 3;
grid-row-end: 4;
}
要熟悉基于线的网格定位,请尝试通过将项目放置在具有不同列数的网格上,构建一些常见的布局。请记住,如果你没有放置所有项目,任何剩余的项目将根据自动放置规则放置。这可能会导致你想要的布局,但如果某个东西出现在了意料之外的地方,请检查是否已为它设置了位置。
此外,请记住,当你在网格上显式放置项目时,这些项目可以相互重叠。这可能会产生一些不错的效果,但是如果你指定了错误的开始或结束线,你也会最终导致项目重叠错误。 Firefox 网格高亮器 在你学习时非常有用,尤其是当你的网格很复杂时。