了解 CSS 网格:网格模板区域

已发表: 2022-03-10
快速总结 ↬在一个新系列中,Rachel Andrew 分解了 CSS 网格布局规范。 这次,我们来看看如何使用grid-template-areas来放置项目。

使用 CSS 网格布局时,您始终可以将项目从一条网格线放置到另一条网格线。 但是,还有另一种描述布局的方式,一种本质上是可视化的方式。 在本文中,我们将学习如何使用grid-template-areas属性来定义网格上的位置,并了解该属性是如何工作的。

如果您错过了本系列之前的文章,您可以在这里找到它们:

  • 第 1 部分:创建网格容器
  • 第 2 部分:网格线
  • 第 3 部分:网格模板区域

grid-template-areas描述布局

grid-template-areas属性接受一个或多个字符串作为值。 每个字符串(用引号括起来)代表网格的一行。 您可以在使用grid-template-rowsgrid-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 示例。

请参阅 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Simple grid-template-areas 示例。

如果您使用 Firefox Grid Inspector,那么您可以看到区域名称和网格线,表明每个项目确实跨越了两行和两列轨道——所有这些都没有对项目本身进行任何基于行的定位。

四个项目的网格,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";

我现在有两个没有内容的单元格。 第三项仅显示在网格的最后一行。

一个项目现在只跨越一行,Firefox Grid Inspector 突出显示这些行
现在网格中有空格

您只能定义每个区域一次,这意味着您不能使用此属性将内容复制到网格上的两个位置! 因此,以下值将无效并导致整个属性被忽略,因为我们复制了区域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-areasgrid-area

每个区域都需要是一个完整的矩形的原因是它需要与您可以使用基于线的放置创建的形状相同。 如果我们坚持上面的示例,我们可以像在下一个 CodePen 中那样使用网格线进行布局。 在这里,我像以前一样创建了我的网格。 然而,这一次,我使用网格线来创建定位,使用了常用的grid-column-startgrid-column-endgrid-row-startgrid-row-end属性。

请参阅 Rachel Andrew (@rachelandrew) 在 CodePen 上的钢笔网格线放置。

请参阅 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

如果您使用 ident(在网格布局中称为命名区域),则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-endgrid-column-start相同,则结束线被丢弃,本质上该值设置为 auto,因此我们像编号版本一样跨越一个轨道。

如果我们错过了第三个值grid-row-end ,也会发生同样的事情; 它与grid-row-start相同,因此变为auto

查看下一个 CodePen 示例,了解如何使用每个grid-area以及如何更改项目的布局:

请参阅 CodePen 上 Rachel Andrew (@rachelandrew) 的网格区域中的 Pen Missing idents。

请参阅 CodePen 上 Rachel Andrew (@rachelandrew) 的网格区域中的 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。

请参阅 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。

请参阅 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-areagrid-area属性来创建布局的内幕。 如果您之前没有使用过这种布局方法,请尝试一下。 我发现这是一种尝试布局的好方法,并且在设计布局原型时经常使用它——即使出于某种原因,我们最终将在生产版本中使用不同的方法。

CSS 中的溢出和数据丢失

CSS 旨在使您的内容保持可读性。 让我们探讨一下您可能会在网页设计中遇到溢出的情况,以及 CSS 如何演变为创建更好的方法来管理和设计未知数量的内容。 阅读相关文章 →