【译】理解CSS网格:网格模板区域

使用网格模板区域描述布局
grid-template-areas属性接受一个或多个字符串作为值。每个字符串(用引号括起来)表示网格中的一行。可以使用网格模板行和网格模板列定义的网格上的属性,也可以创建布局,在这种情况下,所有行都将自动调整大小。
下面的属性和值描述了一个具有四个区域的网格——每个区域跨越两个列轨道和两个行轨道。一个区域通过在你希望它覆盖的所有单元格中重复名字来跨越多个轨迹:
grid-template-areas: "one one two two" "one one two two" "three three four four" "three three four four";
通过使用网格区域属性使用缩进来命名项,从而将项放置到布局中。因此,如果我想要将一个带有测试类的元素放到名为one的网格区域中,我使用以下CSS:
.test { grid-area: one; }
您可以在下面的代码页示例中看到这一点。我有四个项目(类一至类四);它们使用grid-area属性分配给相关的网格区域,因此在网格中正确的框中显示它们。
如果您使用Firefox网格检查器,那么您可以看到区域名称和网格线,它们表明每个项目确实跨越了两个行和两个列轨道—所有这些都不需要对项目本身进行任何基于行的定位。
使用网格模板区域的规则
在以这种方式创建布局时,有一些规则。违反规则将使该值无效,因此您的布局将不会发生。第一个规则是必须描述一个完整的网格,即必须填充网格上的每个单元格。
如果您确实希望将一个单元格(或多个单元格)保留为空,可以通过插入a来实现。或系列如…它们之间没有空间。
因此,如果我改变网格-模板-区域的值如下:
grid-template-areas: "one one two two" "one one two two" ". . four four" "three three four four";
我现在有两个没有内容的单元格。项目3只显示在网格的最后一行。
一个项目现在只跨一行,Firefox网格检查器高亮显示这些行
您只能定义每个区域一次,这意味着您不能使用此属性将内容复制到网格上的两个位置!所以下面的值是无效的,会导致整个属性被忽略,因为我们已经复制了面积3:
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 three three" "one one two two" "three three four four" "three three four four";
格式化字符串
我喜欢像上面那样显示网格模板区域的值(每个字符串表示前一行下面的一行)。这给了我布局的可视化表示。
为了帮助解决这个问题,有必要在每个单元格之间添加额外的空白字符,并使用多个空白字符。表示空单元格的字符。
在下面的值中,我在较小的单词之间使用了多个空白字符,也使用了多个空白字符。字符使空单元格对齐:
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";
解释网格模板区域和网格区域
每个区域需要是一个完整的矩形的原因是,它需要与您可以使用基于行的布局创建的形状相同。如果我们继续使用上面的例子,我们可以像在下一个代码页中那样使用网格线进行布局。在这里,我已经创建了我的网格。然而,这一次,我使用网格线来创建定位,使用的是long - and grid-column-start、grid-column-end、grid-row-start和grid-row-end属性。
注意:如果您阅读了我的上一篇文章“理解CSS Grid: Grid Lines”,您将知道可以使用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; }
网格区域属性很有趣,因为它可以获取行号和行名。理解它在每种模式下的不同行为方式也很重要。
使用带有行号的网格区域
如果您使用带有行号的网格区域属性,那么这些行将按照上面描述的顺序分配。
如果您丢失了任何值——因此提供了1、2或3行数字——丢失的值被设置为auto,这意味着该区域将跨越1个轨道(这是默认值)。因此,下面的CSS将放置一个项目grid-row-start: 3,所有其他值都设置为auto,因此,项目将自动放置在第一个可用的列跟踪中,并跨越一个行跟踪和一个列跟踪。
grid-area: 3;
使用带有标识的网格区域
如果使用ident(在网格布局中称为命名区域),那么Grid -area属性也有四行。如果您已经在网格中命名了“理解CSS网格:创建一个网格容器”中描述的行,那么您可以像使用编号行一样使用这些命名行。
但是,当您遗漏某些行时所发生的情况与使用idents而不是number时所发生的情况是不同的。
下面,我创建了一个网格与命名线和使用网格区域放置一个项目(缺少最后的价值):
.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是相同的,那么结束行就会被丢弃,本质上该值被设置为auto,因此我们就像编号版本中那样跨越一条轨迹。
如果我们忽略了第三个值grid-row-end,也会发生同样的事情;它与grid-row-start相同,因此变成了auto。
看看下一个代码页的例子如何使用每个网格区域,然后如何改变项目的布局:
这就解释了为什么网格区域使用表示区域名称的单个值标识。
当我们使用grid-template-areas属性创建一个命名区域时,每个区域的边缘都可以通过与您使用的区域名称相同的行名称来引用。在我们的例子中,我们可以使用命名区域1,并使用以下命名行放置我们的项目:
.one { grid-row-start: one; grid-row-end: one; grid-column-start: one; grid-row-end: one; }
如果该行是-start行,则解析为列或行的开始端。如果是-end行,则解析为列或行的结束行。
这意味着,当我们说网格区域:1时,我们省略了网格区域简写的最后三个值;它们最终都是第一个值的副本——在我们的示例中,所有的值都是一个,项目的位置与我们的longhand用法一样。
在网格布局中命名的方式很聪明,并且可以实现一些有趣的东西,我在之前的文章“在CSS网格布局中命名”和“用CSS网格和命名列编辑设计模式”中已经介绍过。
使用网格模板区域时分层项
在使用网格模板区域时,每个单元格只能有一个名称,但是,您仍然可以以这种方式在主布局之后向网格添加其他项。您可以像往常一样使用行号。
在下面的代码页示例中,我添加了一个附加项,并使用基于行的定位对已经定位的项进行定位:
您还可以使用在创建通常的列或行时定义的行名称。更好的是,您将拥有一些由区域的形成所创建的行名称。我们已经看到了如何用区域的名称获得四行名称。您还可以在每个区域的开始边缘得到一行-start附加到该区域的名称,并在每个区域的结束边缘得到一行-end附加。
因此,命名为one的区域有命名为one-start的开始边缘线和命名为one-end的结束边缘线。
然后,您可以使用这些隐式行名称在网格中放置项目。如果您在不同的断点处重新定义网格,只要您总是希望放置的项位于某个行名称之后,那么这将非常有用。
在响应式设计中使用网格模板区域
我经常在组件库中构建组件,我发现使用网格模板区域可以帮助您准确地查看来自CSS的组件的外观。在不同的断点处重新定义组件也非常简单,除了更改可用列轨道的数量外,有时还可以重新定义网格模板区域的值。
在下面的CSS中,我为组件定义了一个列布局。接下来,在最小宽度600px处,我重新定义了列的数量和网格模板区域的值,以便创建一个包含两列的布局。这种方法的好处是任何人看到这个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; }
可访问性
在使用此方法时,您需要知道,很容易将内容四处移动,并导致从底层源顺序断开可视显示的问题。任何在网站上随意切换的人,或者一边看屏幕一边说内容的人,都将使用源文件中内容的顺序。通过移动显示的顺序,你可以创建一个非常混乱的,不连贯的体验。不要使用这种方法来移动东西,同时也要确保源文件的顺序是合理的,并与视觉体验相匹配。
总结
这就是使用网格模板区域和网格区域属性创建布局的内幕。如果您以前没有使用过这种布局方法,请尝试一下。我发现这是一种很好的体验布局的方式,并且经常在原型化布局时使用它——即使由于这样或那样的原因,我们最终会在产品版本中使用不同的方法。