使用 CSS 网格布局时,您始终可以将项目从一条网格线放置到另一条网格线。但是,还有另一种描述布局的方式,一种本质上是可视化的方式。在本文中,我们将学习如何使用该grid-template-areas
属性来定义网格上的位置,并了解该属性是如何工作的。
如果您错过了本系列之前的文章,您可以在这里找到它们:
grid-template-areas
该grid-template-areas
属性接受一个或多个字符串作为值。每个字符串(用引号括起来)代表网格的一行。您可以在使用grid-template-rows
and定义的网格上使用该属性grid-template-columns
,或者您可以创建布局,在这种情况下,所有行都将自动调整大小。
以下属性和值描述了一个具有四个区域的网格——每个区域跨越两个列轨道和两个行轨道。通过在您希望它覆盖的所有单元格中重复名称,使一个区域跨越多个轨道:
grid-template-areas: "one one two two"
"one one two two"
"three three four four"
"three three four four";
grid-area
通过使用该属性使用 ident 命名,将项目放置到布局中。因此,如果我想将一个类的元素test
放入名为 的网格区域中one
,我使用以下 CSS:
.test {
grid-area: one;
}
您可以在下面显示的 CodePen 示例中看到这一点。我有四个项目(一到四级);这些使用grid-area
属性分配给相关的网格区域,因此显示在正确的框中的网格上。
请参阅Rachel Andrew ( @rachelandrew ) 在CodePen上的 Pen Simple grid-template-areas 示例。
如果您使用 Firefox Grid Inspector,那么您可以看到区域名称和网格线,表明每个项目确实跨越了两行和两列轨道——所有这些都没有对项目本身进行任何基于行的定位。
每个项目跨越两行和两列
grid-template-areas
#以这种方式创建布局时有一些规则。违反规则将使值无效,因此您的布局不会发生。第一条规则是您必须描述一个完整的网格,即必须填充网格上的每个单元格。
如果您确实想将一个单元格(或多个单元格)留作空白,您可以通过插入一个.
或系列来做到这一点,例如...
它们之间没有空格。
因此,如果我将值更改grid-template-areas
如下:
grid-template-areas: "one one two two"
"one one two two"
". . four four"
"three three four four";
我现在有两个没有内容的单元格。第三项仅显示在网格的最后一行。
现在网格中有空格
您只能定义每个区域一次,这意味着您不能使用此属性将内容复制到网格上的两个位置!因此,以下值将无效并导致整个属性被忽略,因为我们复制了该区域three
:
grid-template-areas: "one one three three"
"one one two two"
"three three four four"
"three three four four";
您不能创建非矩形区域,因此该属性不能用于创建“L”或“T”形区域 - 使以下值也无效:
grid-template-areas: "one one two two"
"one one one one"
"three three four four"
"three three four four";
我喜欢显示grid-template-areas
上面的值(每个字符串代表前一行下方的一行)。这给了我一个布局的直观表示。
为了解决这个问题,在每个单元格之间添加额外的空白字符以及使用多个.
字符表示空单元格是很有价值的。
在下面的值中,我在较小的单词之间使用了多个空白字符,并且还使用了多个.
字符,因此空单元格排列:
grid-template-areas: "one one two two"
"one one two two"
"..... ..... four four"
"three three four four";
也就是说,将所有字符串放在一行中也是完全有效的,因此我们可以将示例编写如下:
grid-template-areas: "one one two two" "one one two two" "three three four four" "three three four four";
grid-template-areas
和grid-area
#每个区域都需要是一个完整的矩形的原因是它需要与您可以使用基于线的放置创建的形状相同。如果我们坚持上面的示例,我们可以像在下一个 CodePen 中那样使用网格线进行布局。在这里,我像以前一样创建了我的网格。然而,这一次,我使用网格线来创建使用简写grid-column-start
的grid-column-end
、grid-row-start
和grid-row-end
属性的定位。
请参阅Rachel Andrew ( @rachelandrew ) 在CodePen上的钢笔网格线放置。
注意:如果您阅读了我之前的文章“理解 CSS 网格:网格线”,您就会知道可以将其grid-area
用作同时声明所有四行的简写。
这意味着我们还可以使用以下行顺序创建布局:
grid-row-start
grid-column-start
grid-row-end
grid-column-end
.one {
grid-area: 1 / 1 / 3 / 3;
}
.two {
grid-area: 1 / 3 / 3 / 5;
}
.three {
grid-area: 3 / 1 / 5 / 3;
}
.four {
grid-area: 3 / 3 / 5 / 5;
}
该grid-area
属性很有趣,因为它可以采用行号和行名。了解它在每种模式下的不同行为方式也很重要。
grid-area
行号 #如果您将grid-area
属性与行号一起使用,则按上述顺序分配行。
如果您错过任何值——因此提供 1、2 或 3 个行号——缺失值将设置为auto
这意味着该区域将跨越 1 个轨道(这是默认值)。因此,下面的 CSS 将放置一个grid-row-start: 3
所有其他值都设置为 auto 的项目,因此,该项目将自动放置在第一个可用的列轨道中,并跨越一个行轨道和一个列轨道。
grid-area: 3;
grid-area
标识 #如果您使用标识(在网格布局中称为命名区域),则该grid-area
属性也需要四行。如果您已按照“理解 CSS 网格:创建网格容器”中的描述在网格上命名线,那么您可以像使用编号线一样使用这些命名线。
但是,当您错过某些行时会发生什么与您使用标识而不是数字时发生的情况不同。
下面,我创建了一个带有命名线的网格并用于grid-area
放置一个项目(缺少最终值):
.grid {
display: grid;
grid-template-columns:
[one-start three-start] 1fr 1fr
[one-end three-end two-start four-start] 1fr 1fr [two-end four-end];
grid-template-rows:
[one-start two-start] 100px 100px
[one-end two-end three-start four-start] 100px 100px [three-end four-end];;
}
.two {
grid-area: two-start / two-start / two-end;
}
这意味着我们缺少grid-column-end
. 规范说,在这种情况下,grid-column-end
应该使用grid-column-start
. 如果grid-column-end
和grid-column-start
相同,则结束线被丢弃,本质上该值设置为自动,因此我们像编号版本一样跨越一个轨道。
如果我们错过了第三个值,也会发生同样的事情grid-row-end
;它变得与 相同grid-row-start
,因此变为auto
。
看看下一个 CodePen 示例,了解如何grid-area
使用每个以及如何更改项目的布局:
请参阅Rachel Andrew ( @rachelandrew ) 在CodePen 上的网格区域中的 Pen Missing idents。
这然后解释了为什么grid-area
使用表示区域名称的单个值 ident。
当我们使用该grid-template-areas
属性创建一个命名区域时,每个区域的边缘都可以通过与您使用的区域名称相同的线名来引用。在我们的例子中,我们可以将我们的区域命名one
并使用命名行放置我们的项目,如下所示:
.one {
grid-row-start: one;
grid-row-end: one;
grid-column-start: one;
grid-row-end: one;
}
如果该行是-start
一行,则one
解析为列或行的开始端。如果是-end
一行,则one
解析为列或行的结束行。
这意味着当我们说 时grid-area: one
,我们省略了grid-area
简写的最后三个值;它们最终都成为第一个值的副本——在我们的例子中,所有这些都变成one
了,并且项目的放置方式与我们的普通用法一样。
网格布局中的命名方式很聪明,并且可以实现一些有趣的事情,我在之前的文章“ CSS 网格布局中的命名”和“使用 CSS 网格和命名列的编辑设计模式”中已经写过。
grid-template-areas
#使用 时,每个单元格只能占用一个名称grid-template-areas
,但是,您仍然可以在以这种方式进行主布局后向网格中添加其他项目。您可以像往常一样使用行号。
在下面的 CodePen 示例中,我添加了一个附加项目,并使用基于行的定位将其定位在已定位的项目上:
请参阅Rachel Andrew ( @rachelandrew ) 在CodePen上的 Pen Placeing an item with line numbers。
您还可以使用在创建常用列或行时定义的行名称。更好的是,您将拥有一些由区域形成创建的线名。我们已经看到了如何获得带有区域名称的四个行名称。您还会在每个区域的起始边缘获得一条-start
附加到区域名称的线,以及在每个区域的结束边缘-end
附加一条线。
因此,命名区域one
具有命名为的起始边线和命名为one-start
的结束边线one-end
。
然后,您可以使用这些隐式行名称将项目放置在网格上。如果您在不同的断点处重新定义网格,只要您始终希望放置的项目位于某个行名之后,这将很有用。
请参阅Rachel Andrew ( @rachelandrew ) 在CodePen上的 Pen Placeing an item with implicit line names。
我经常在组件库中构建组件,我发现使用grid-template-areas
它有助于从 CSS 中准确查看组件的外观。grid-template-areas
除了更改可用列轨道的数量之外,通过重新定义有时的值来重新定义不同断点处的组件也非常简单。
在下面的 CSS 中,我为我的组件定义了一个单列布局。接下来,在最小宽度为 600 像素的情况下,我重新定义了列数以及 的值,grid-template-areas
以便创建具有两列的布局。这种方法的好处是,任何查看此 CSS 的人都可以看到布局是如何工作的!
.wrapper {
background-color: #fff;
padding: 1em;
display: grid;
gap: 20px;
grid-template-areas:
"hd"
"bd"
"sd"
"ft";
}
@media (min-width: 600px) {
.wrapper {
grid-template-columns: 3fr 1fr;
grid-template-areas:
"hd hd"
"bd sd"
"ft ft";
}
}
header { grid-area: hd; }
article {grid-area: bd; }
aside { grid-area: sd; }
footer { grid-area: ft; }
使用此方法时需要注意,它很容易四处移动并导致视觉显示与底层源订单断开连接的问题。任何在网站上浏览的人,或者在说出内容的同时观看屏幕的人,都将使用源中的顺序。通过从该顺序移动显示,您可以创建一个非常混乱、断开连接的体验。不要使用这种方法来移动东西而不确保源的顺序合理并匹配视觉体验。
这就是使用grid-template-area
andgrid-area
属性创建布局的基本内容。如果您之前没有使用过这种布局方法,请尝试一下。我发现这是一种尝试布局的好方法,并且在设计布局原型时经常使用它——即使出于某种原因,我们最终将在生产版本中使用不同的方法。