grid-area

Avatar of Mojtaba Seyedi
Mojtaba Seyedi

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

grid-area CSS 属性是一个简写属性,它通过设置 grid-row-startgrid-column-startgrid-row-endgrid-column-end 的值在一个声明中指定网格项目的在网格布局中的位置和大小。

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}

.grid-item:nth-child(2) {
  grid-area: 2 / 4 / 4 / 6;

  /* is equivalent to: */
  grid-row-start: 2;
  grid-column-start: 4;
  grid-row-end: 4;
  grid-column-end: 6;
}

由于 CSS Grid 的默认 自动放置行为,此示例中的第二个网格项目通常会被放置在网格第一行的第二列。但是,由于我们声明了 grid-area 并将其设置为使网格项目的起始和结束边缘与我们所需的网格线对齐,因此该项目移动到第二行和第四列,并在两个方向上跨越了两个轨道以满足正确的结束网格线。

使用 grid-area CSS 属性设置第二个网格项目的位置和大小。

组成属性

如前所述,grid-area 属性是一个简写属性,它组合了四个属性

语法

grid-area: <grid-line> [ / <grid-line> ]{0,3}
完整定义
<grid-line> =
  auto |
  <custom-ident> |
  [ [ <integer [−∞,−1]> | <integer [1,∞]> ] && <custom-ident>? ] |
  [ span && [ <integer [1,∞]> || <custom-ident> ] ]

  • 初始值: auto
  • 应用于: 网格项目和绝对定位的盒子,其包含块是网格容器
  • 继承:
  • 计算值: 其详细属性指定的计算值
  • 动画类型: 离散

此属性最多可以采用四个值,这些值由正斜杠 (/) 分隔。

四个值

如果指定了四个 <grid-line>

  • 第一个值设置 grid-row-start 属性。
  • 第二个值设置 grid-column-start 属性。
  • 第三个值设置 grid-row-end 属性。
  • 第四个值设置 grid-column-end 属性。
.grid-item {
  grid-area: 2 / 4 / 3 / 6;

  /* is equivalent to: */
  grid-row-start: 2;
  grid-column-start: 4;
  grid-row-end: 3;
  grid-column-end: 6;
}

三个值

当指定三个值时grid-column-end 将被省略。如果 grid-column-start<custom-ident>,则 grid-column-end 将设置为该 <custom-ident>;否则,将其设置为 auto

  • 第一个值设置 grid-row-start 属性。
  • 第二个值设置 grid-column-start 属性。
    • 如果该值为 <custom-ident>,它还会设置 grid-column-end 属性。
    • 否则,grid-column-end 将设置为 auto
  • 第三个值设置 grid-row-end 属性。
/* <custom-ident> */
.grid-item {
  grid-area: 2 / area / 4;
  
  /* is equivalent to */
  grid-row-start: 2;
  grid-column-start: area;
  grid-row-end: 4;
  grid-column-end: area;
}

/* <grid-line> */
.grid-item {
  grid-area: 2 / 4 / 3;

  /* is equivalent to: */
  grid-row-start: 2;
  grid-column-start: 4;
  grid-row-end: 3;
  grid-column-end: auto;
}

两个值

当指定两个值时, grid-row-endgrid-column-end 将被省略。如果 grid-row-startgrid-column-start 值为 <custom-ident>,则 grid-row-endgrid-column-end 将设置为该 <custom-ident>;否则,将其设置为 auto

  • 第一个值设置 grid-row-start 属性。
    • 如果该值为 <custom-ident>,它还会设置 grid-row-end 属性。
    • 否则,grid-row-end 将设置为 auto
  • 第二个值设置 grid-column-start 属性。
    • 如果该值为 <custom-ident>,它还会设置 grid-column-end 属性。
    • 否则,grid-column-end 将设置为 auto
/* <custom-ident> */
.grid-item {
  grid-area: area / 4;
  
  /* is equivalent to */
  grid-row-start: area;
  grid-column-start: 4;
  grid-row-end: area;
  grid-column-end: auto;
}

/* another <custom-ident> example */
.grid-item {
  grid-area: area / another-area;
  
  /* is equivalent to */
  grid-row-start: area;
  grid-column-start: another-area;
  grid-row-end: area;
  grid-column-end: another-area;
}

/* <grid-line> */
.grid-item {
  grid-area: 2 / 4;

  /* is equivalent to */
  grid-row-start: 2;
  grid-column-start: 4;
  grid-row-end: auto;
  grid-column-end: auto;
}

单个值

当指定一个值时,如果 grid-row-start<custom-ident>,则所有四个组成属性都将设置为该值。否则,将其设置为 auto

/* <custom-ident> */
.grid-item {
  grid-area: area;
  
  /* is equivalent to */
  grid-row-start: area;
  grid-column-start: area;
  grid-row-end: area;
  grid-column-end: area;
}

/* <grid-line> */
.grid-item {
  grid-area: 2;

  /* is equivalent to */
  grid-row-start: 2;
  grid-column-start: auto;
  grid-row-end: auto;
  grid-column-end: auto;
}

理解此语法

基于值数量的不同场景(更不用说 <custom-ident> 案例)起初可能看起来很复杂且奇怪。但是,如果您稍微思考一下,就会发现这一切都很有道理。

以下面的网格项目为例

.grid-item {
  grid-area: 2 / 4 / 3;
}

这里,grid-column-end 被省略了(因为这是三值语法),并且 grid-column-start 设置为 4grid-column-end 属性不能也为 4,因为网格项目的起始和结束边缘将指向同一条线。浏览器不会将起始边缘对齐到 4,并且会将网格项目跨度设置为一列作为默认行为。这就是为什么当某个边缘没有值时,它会被设置为 auto — 以防其另一条边指向具有数值的网格线。

现在,如果 grid-column-start 值设置为名称而不是数字呢?例如,x 而不是 4

.grid-item {
  grid-area: 2 / x / 3;
}

x 值可以是网格线或网格区域的名称。如果存在名为 x 的网格线,则 grid-column-end 也将设置为 x,但由于网格项目的两个列边缘都指向同一条网格线 — x — 浏览器再次默认行为是表现得好像 grid-column-end 设置为 auto,并且网格项目跨度为一列。

另一方面,如果存在一个名为x的网格区域,则grid-column-start设置为该网格区域的起始边缘,而grid-column-end设置为其结束边缘。

当你在代码中看到它时,理解所有这些就容易多了。

.grid-item {
  grid-area: 2 / x / 3;

  /* is equivalent to */
  grid-row-start: 2;
  grid-column-start: x-start;
  grid-row-end: 3;
  grid-column-end: x-end;
}

/* Keyword value */
grid-area: auto;

/* <custom-ident> value */
grid-area: my-area;
grid-area: main-start / sidebar-start;
grid-area: main-start / sidebar-start / footer-start / main-end;
grid-area: line1 / line2 / line3 / line4;

/* <integer> + <custom-ident> values */
grid-area: 3;
grid-area: 2 / -3;
grid-area: main 2;
grid-area: 2 a / 4 b / 2 x;

/* span + <integer> + <custom-ident> values */
grid-area: span 3;
grid-area: 1 / 3 / span 2 / 5;
grid-area: 1 / span myline;
grid-area: 2 / span gridline 3;

/* Global values */
grid-area: inherit;
grid-area: initial; /* same as `auto` */
grid-area: revert;
grid-area: revert-layer;
grid-area: unset;

auto

这是默认值。它表示默认跨度 (1) 和自动放置行为,这意味着网格项目会自动放置在下一个可用的空网格单元格中。

<custom-ident>

此语法允许你使用整数来引用编号的网格线,或使用字符串来引用命名网格线命名网格区域。换句话说,你可以通过其数字索引名称指定网格线到网格项目的边缘。

按行号定位项目

在每个网格轨道之前和之后有两条网格线,并自动为它们分配了数字索引,从数字 1 开始。

演示行和列网格轨道的索引。

在本文章的第一个示例中,我们使用了此语法通过其索引 (24) 来引用第二和第四行网格线,以使网格项目的起始和结束边缘与第二和第三行的起始和结束边缘对齐。此外,我们还引用了第四和第六列网格线,以使网格项目的起始和结束边缘与第四和第五列的起始和结束边缘对齐。

.grid-item:nth-child(2) {
  grid-area: 2 / 4 / 4 / 6;
}

请注意,你也可以使用负数来引用网格线,但它是从网格的结束边缘开始计数的。以下代码指向先前示例中的相同网格线,但反向计数。

.grid-item:nth-child(2) {
  grid-column: -4 / -4 / -2 / -2; /* same as: grid-area: 2 / 4 / 4 / 6; */
}

请注意,负整数已分配给我们的网格。

使用grid-area CSS 属性将第二个网格项目放置到第二和第三行以及第四和第五列中。
按行名定位项目

你可以使用grid-template-columnsgrid-template-rows 基于行的布局网格属性为网格线分配自定义名称,以便通过其名称来引用该线。

让我们回到我们的示例,并像这样命名列和行轨道线。

.grid {
  display: grid;
  grid-template-rows: 100px [row2] 100px 100px [row4] 100px;
  grid-template-columns: 1fr 1fr 1fr [fourth] 1fr 1fr [second-to-last] 1fr;
}

我们可以通过自定义名称 (row2row4fourthsecond-to-last) 来引用第三和第五行,而不是使用它们的索引值 (分别为 2446)。

.grid-item:nth-child(2) {
  grid-area: row2 / fourth / row4 / second-to-last; /* same as index numbers 2 / 4 / 4 / 6 */
}

请注意,<custom-ident> 不能使用 span 值。span 是网格布局属性的保留关键字(例如 grid-column: 1 / span 2)。

按网格区域定位项目

在使用grid-template-areas 属性定义网格区域时,你会根据区域的名称免费获得隐式行名。例如,名为 content 的网格区域会在其前面生成一条名为 content-start 的线,在其后面生成一条名为 content-end 的线。你可以引用这些线来设置网格项目的位置。

.grid-item:nth-child(2) {
  grid-area: content-start / content-start / content-end / content-end;
}

或者,你可以引用区域的名称,以将项目定位在名为 content 的区域的起始和结束线处。

.grid-item:nth-child(2) {
  grid-area: content;
}

这是一个完整的示例。

<body>
  <header></header>
  <main></main>
  <aside></aside>
  <footer></footer>
</body>
body {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: min-content 1fr min-content;
  grid-template-areas:
    "header header header"
    "content content sidebar"
    "footer footer footer";
}

header {
  grid-area: header;
}

main {
  grid-area: content;
}

aside {
  grid-area: sidebar;
}

footer {
  grid-area: footer;
}

这将网格元素的位置设置为我们希望在网格中的位置。

使用grid-area CSS 属性将网格项目放置到网格区域中。

<integer> && <custom-ident>?

此语法风格允许你在存在重复名称时通过网格线定位网格项目。如果存在具有相同名称的网格线,则此语法有助于指定你正在引用的哪条线。

.grid {
  display: grid;
  grid-template-columns: [a] 1fr [b] 1fr [b] 1fr [b] 1fr [b];
  grid-template-rows: [x] 1fr [y] 1fr [y] 1fr [y] 1fr [y];

  /*
    Using repeat() function also gives you repeated named grid line, for example:
    grid-template-columns: repeat(3, [b] 1fr);
  */
}

假设你想在行轨道中选择第三条线,但该线的名称与第二、第四和最后一条网格线相同——它们都称为 y。由于名为 y第二条线是第三条网格线,因此你可以使用 2 将其选为起点。以下示例中,grid-area 的其他值的计数方式相同。

.grid-item:nth-child(2) {
  grid-area: 2 y / 3 b / 4 y / 4 b;

  /* This is equivalent to: */
  grid-row-start: 2 y;
  grid-column-start: 3 b;
  grid-row-end: 4 y;
  grid-column-end: 4 b;
}

请注意,值的顺序无关紧要。我们也可以像这样编写前面的代码。

.grid-item:nth-child(2) {
  grid-area: y 2 / b 3 / y 4 / b 4;
}

与之前的语法一样,你也可以使用负整数从网格的结束边缘开始计数网格线。在我们的示例中,如果我们想引用相同的线,我们可以从网格的结束边缘开始计数并像这样编写:

.grid-item:nth-child(2) {
  grid-area: -3 y / -2 b / -1 y / -1 b;
}

请注意,整数不能为零。

span && [ <integer> || <custom-ident> ]

此语法允许网格项目跨越网格轨道。它可以通过三种不同的方式指定。

请注意,如果在此语法中任何地方都没有指定整数,则默认值为 1

span <integer>

使用后跟整数的 span 关键字表示网格项目从特定网格线跨越的轨道数。例如,如果我们希望网格项目跨越三个行轨道和两个列轨道到其起始边缘,我们可以应用以下值。

.grid-item:nth-child(2) {
  grid-area: span 3 / span 2;

  /* This is equivalent to */
  grid-row-start: span 3;
  grid-column-start: span 2;
  grid-row-end: auto;
  grid-column-end: auto;
}
网格项目使用grid-area CSS 属性跨越两列和三行。
span <custom-ident>

也可以将 span 关键字与网格线的名称组合使用,以使网格项目扩展到到达指定的网格线。

.grid-item:nth-child(3) {
  grid-area: auto / 3 / auto / span lastline;
}

由于网格项目的起始线已知 (3),因此我们可以使项目扩展到它到达名为 lastline 的列网格线。

网格项目使用grid-area CSS 属性跨越网格,直到到达指定的名为 lastline 的网格线。
span <custom-ident> <integer>

如果指定的网格线名称分配给多个网格线——换句话说,如果我们有重复的命名网格线——我们需要说明我们想要定位哪些网格线。为此,我们可以向我们的值添加一个整数,指定我们正在引用的哪条网格线。

以以下网格为例。

.grid-container {
  display: grid;
  grid-template-columns: [y] 1fr [x] 1fr [x] 1fr [y] 1fr [x] 1fr [x];
}

.grid-item:nth-child(3) {
  grid-area: 2 / 2 / 4 / span x 2;
}

我们将网格项目的起始线设置为第二列线。然后我们希望它向前扩展,直到它到达名为 x 的网格线。并且由于我们希望它是第二条 x 网格线,因此我们最终得到 span x 2

因此,我们的网格项目从第二行开始扩展,如下所示。它遇到的第一条线是第一条 x,然后是 y,最后,它到达了所需的第二条名为 x 的线。

使用grid-area 属性设置网格项目从第二列线到第二个名为 x 的线的位置。

这种语法在你想使用网格线名称将网格项跨越到该网格线时很有帮助。但要注意,使用这种方法时,可能存在多个同名的网格线,所以我们会添加一个整数来说明我们想要该网格线的第N个。

请参阅grid-row-startgrid-row-endgrid-column-startgrid-column-end,以获取有关每个组成属性的语法的更多信息和示例。

示例

让我们看几个例子来演示如何使用grid-area将项目放置在网格上。

创建多层横幅

假设您的设计团队将此图形提供给您

Three overlapping images with a blockquote positioned in the bottom-right corner.

他们还提供了另一个版本来向您展示它是在网格上设计的

Showing teh grid lines for a design as an overlay.

让我们首先设置我们的HTML

<figure>
  <img class="back" src="back.jpg" alt="Please">
  <img class="middle" src="middle.jpg" alt="fill your alt">
  <img class="front" src="front.jpg" alt="properly">
  <figcaption>Freedom is the oxygen of the soul...</figcaption>
</figure>

设计中有十四列和九行。我们可以这样写出来

figure {
  display: grid;
  grid-template-columns: repeat(14, 50px);
  grid-template-rows: repeat(9, 50px);
}

我们需要将所有这些子<img>元素放置到其正确的网格区域中。为此,我们使用grid-area属性

.back {
  grid-area: 1 / 3 / -2 / -1;
}

.middle {
  grid-area: 2 / 1 / 7 / 9;
}

.front {
  grid-area: 4 / 4 / -1 / -3;
}

figcaption {
  grid-area: -3 / -4 / -1 / -1;
}

您可以在下图中看到结果

Showing a grid layout with an overlay revealing the layout's grid lines.

查看演示以检查有关此示例的更多详细信息

堆叠网格项

在跨网格定位项目时,我们可以将它们彼此堆叠或重叠。这使我们能够在某些情况下使用 CSS Grid 作为绝对定位的替代方案。例如,我们可以将字幕层放在图像顶部,而无需使用position属性,如下所示

<figure>
  <img src="image.png" alt="how dare you leave alt empty?">
  <figcaption>The caption of our image</figcaption>
</figure>
figure {
  display: grid;
}

img,
figcaption {
  grid-area: 1 / 1 / -1 / -1;
}

这是我们得到的结果

默认情况下,网格项按源顺序堆叠,但您可以使用z-index属性控制其级别。在以下示例中,我们重叠了一些项目,并使用z-index属性将第二个项目带到堆叠上下文中最高级别

.item:nth-child(2) {
  grid-area: 2 / 2 / 4 / 4;
  z-index: 1;
}
使用z-index属性将第二个网格项置于堆栈顶部。

可访问性

在使用网格放置属性时需要注意的一件事是重新排列项目引起的问题。当您更改项目的顺序时,只有网格项目的视觉顺序会发生变化,并且该顺序可能与原始文档顺序不同。这可能会导致在键盘上通过文档进行制表或收听以与 HTML 相同的顺序读取内容的屏幕阅读器的人员体验非常糟糕。

因此,当元素的 HTML 顺序很重要时,请避免更改网格项目的顺序。例如,它可能对随机图像库有好处,但对您的表单输入可能不太好。

但是,在撰写本文时,有一个提案来解决这个问题,希望将来能解决这个顾虑。

演示

您可以在演示中更改grid-area属性的值以查看对第三个网格项的影响

浏览器支持

更多信息