grid-row-end

Avatar of Mojtaba Seyedi
Mojtaba Seyedi

DigitalOcean 提供适合您旅程各个阶段的云产品。 立即开始使用 $200 免费额度!

grid-row-end CSS 属性是 CSS 网格布局规范 的一部分,用于指示网格项目在网格布局中结束的网格行线。 该属性 - 与其他基于线的网格布局属性 - 控制网格项目的尺寸及其在网格上的位置。

.grid-container {
  display: grid;
  grid-template-rows: 100px 100px 100px;
  grid-template-columns: 1fr 1fr 1fr;
}

.grid-item:nth-child(2) {
  grid-row-end: 3; /* Item ends on the third row line */
}

根据 CSS 网格的默认 自动布局 行为,此示例中网格的第二个子元素应放置在第一行和第二列。 但我们对第二行网格线声明了 grid-row-end 位置,将网格项目移至第二行,并将结束边与第三行网格线对齐。

Three by three grid of white rectangles on an orange background. The first item in the second row is green and numbered two.
使用 grid-row-end CSS 网格属性将第二个网格项目移至第二行。

语法

grid-row-end: <grid-line>
完整定义
where
<grid-line> =
  auto |
  <custom-ident> |
  [ [ <integer [−∞,−1]> | <integer [1,∞]> ] && <custom-ident>? ] |
  [ span && [ <integer [1,∞]> || <custom-ident> ] ]

  • 初始值: auto
  • 应用于: 网格项目和其包含块为网格容器的绝对定位框
  • 继承:
  • 计算值: 按指定
  • 动画类型: 离散

/* Keyword value */
grid-row-end: auto;

/* <custom-ident> value */
grid-row-end: myLineName;
grid-row-end: myGridArea;

/* <integer> + <custom-ident> values */
grid-row-end: 3;
grid-row-end: -2;
grid-row-end: main-area 2;
grid-row-end: 3 product-end;

/* span + <integer> + <custom-ident> values */
grid-row-end: span 3;
grid-row-end: span main;
grid-row-end: span myarea 5;

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

auto

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

<custom-ident>

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

通过线号定位项目

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

Three by three grid of white rectangles against an orange background.
此图仅显示网格轨道行的索引

在本文的第一个示例中,我们使用此语法通过索引 (3) 引用第三条网格线,以使用 <custom-ident> 语法将网格项目的结束边与第二行的结束边对齐

.grid-item:nth-child(2) {
  grid-row-end: 3;
}

请注意,您也可以使用负数(例如 -1)来引用网格线,但请记住,它是从网格的结束边开始计数。 以下代码指向上一示例中的相同网格线,但反向计数

.grid-item:nth-child(2) {
  grid-row-end: -2; /* same as 3 */
}

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

Three by three grid of white rectangles on an orange background. The first item in the second row is green and numbered two.
使用 grid-row-end CSS 网格属性将第二个网格项目移至第二行。
通过线名定位项目

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

让我们回到我们的示例,并像以下声明一样为所有行轨道线命名

.grid {
  display: grid;
  grid-template-rows: [first] 100px [second] 100px [third] 100px [last];  
  grid-template-columns: 1fr 1fr 1fr;
}

我们可以通过我们的自定义名称来引用第三行,而不是使用其索引

.grid-item:nth-child(2) {
  grid-row-end: third; /* same as index number 3 */
}

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

通过网格区域定位项目

当使用 grid-template-areas 属性定义网格区域时,您会免费获得 隐式线名,这些线名基于区域的名称。例如,名为 header 的网格区域会在其之前生成一个名为 header-start 的线名,并在其之后生成一个名为 header-end 的线名。您可以参考这些线名来设置网格项目的定位。

.grid-item:nth-child(2) {
  grid-row-end: header-end;
}

或者,您可以参考区域的名称,将项目定位在名为 header 的区域的结束线上

.grid-item:nth-child(2) {
  grid-row-end: header;
}

由于您在本示例中使用的是 grid-row-end 属性,浏览器会理解您想要使用 header 区域的 header-end 线;因此,它会将网格项目的结束边与网格区域的结束边对齐。

以下是一个完整的示例

<body>
  <header></header>
  <main></main>
  <footer></footer>
</body>
body {
  display: grid;
  grid-template-rows: min-content 1fr min-content;   
  grid-template-areas: 
    "header"
    "main"
    "footer";
}

header {
  grid-row-end: header;
}

这将 <header> 元素的定位设置到我们网格中的 header 区域。

<integer> && <custom-ident>?

这种语法可以让你在有重复名称的情况下,通过网格线来定位网格项目。如果网格线上有相同的名称,这种语法可以帮助你指定要参考哪一条线。

.grid {
  display: grid;
  grid-template-rows: [bar] 100px [foo] 100px [bar] 150px [bar];
}

假设你想要选择第四条线,但是这条线与第一条线和第三条网格线具有相同的名称——它们都叫 bar。由于名为 bar第三条线是第四条网格线,你可以使用 3 来选择它作为结束点

.grid-item:nth-child(2) {
  grid-row-end: 3 bar; /* The third `bar` named line which is the fourth line */
}
A single column layout of white rectangles with three rows. The second item is placed in the third row and is green.

注意,顺序并不重要,所以之前的代码也可以这样写

.grid-item:nth-child(2) {
  grid-row-end: bar 3;
}

与之前的语法类似,你可以使用负整数从网格的结束边开始计数网格线。在我们的示例中,如果我们想引用第一个 bar,我们可以从网格的结束边开始计数,并像这样写

.grid-item:nth-child(2) {
  grid-row-end: -3 bar;
}

注意,整数值不能为零,因为线被分配了非零值。

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

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

如果在此语法中没有指定整数,则默认值为 1

span <integer>

使用 span 关键字后跟一个整数表示网格项目跨越的轨道数量,从指定的网格线开始。例如,如果我们希望网格项目在结束边方向跨越三个行轨道,我们可以应用以下值

.grid-item:nth-child(2) {
  grid-row-end: span 3;
}
A three by four grid  where the second item is green, in the second column, and spans the first three rows.
网格项目使用 grid-row-end CSS 属性跨越三行。
span <custom-ident>

您可以将 span 与网格线的名称结合起来,使网格项目扩展到指定的网格线。

.grid-item:nth-child(2) {
  grid-row-start: 3;
  grid-row-end: span lastline;
}

由于网格项目的起始线是已知的 (3),我们可以将项目向结束线方向扩展,直到它遇到名为 lastline 的网格线。

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

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

以下面的网格为例

.grid-container {
  display: grid;
  grid-template-rows: [y] 50px [x] 50px [x] 50px [y] 50px [x] 50px [x];
}

.grid-item:nth-child(2) {
  grid-row-start: 2;
  grid-row-end: span x 2; /* equivalent to grid-row-end: 5; */
}

我们将网格项目的起始线设置为第二条线。然后我们希望它向下扩展,直到它遇到一条名为 x 的网格线。由于我们希望它是名为 x 的第二条线,最终得到了 grid-row-end: span x 2

因此,我们的网格项目从第二条线开始向结束线方向扩展,如下所示。它遇到的第一条线是第一个 x,下一个是名为 y 的,最后它遇到了我们想要的第二个名为 x 的线。

A two-by-five layout where the second item is green, in the first column and spans the second, third, and fourth rows.
使用 grid-row-end CSS 属性将网格项目的定位从第二条线设置为名为 x 的线的第二个实例。

当您想要使用网格线的名称来将网格项目扩展到网格线,但您知道有多条网格线具有相同的名称时,这种语法非常有用,因此我们会添加一个整数来说明我们想要第 N 条网格线。

定位网格项目可能会生成隐式轨道

将网格项目的定位设置为网格线的索引或网格线上不存在的名称,将迫使网格创建隐式轨道以将该位置添加到网格中。

让我们创建一个有两行的网格,并将它的项目的位置设置为不存在的线。在下面的例子中,我们只有两行,并且我们没有给任何网格线命名。因此,没有索引为5的线,也没有名为test的线,但是我们将这些值设置为我们的属性

.grid {
  display: grid;
  grid-template-rows: 100px 100px;
  grid-auto-rows: 100px;
}

.grid-item {
  grid-row-start: span test;
  grid-row-end: 5;
}

由于我们知道网格中有隐式轨道,并且我们希望它们具有大小以便我们可以看到它们,我们向代码中添加了grid-auto-rows`属性。

现在我们已经设置好了一切,让我们看看网格发生了什么

A single column layout with five grid tracks, two of which are implicit.
给网格放置属性赋予不存在的值会导致网格创建隐式轨道以便能够放置网格项目。

我们将grid-row-end设置为5,但是我们显式网格的最后一个索引是3,因此,在网格的末尾创建了两个隐式轨道,为我们提供了索引分别为45的隐式线,元素可以与它们对齐。

另一方面,假设我们将grid-row-end设置为名为test的网格线。同样,由于我们的网格中没有这样的名称,并且因为我们希望该网格线与网格项目的起始边缘对齐,所以在显式网格的块方向的起始侧创建了一个隐式行轨道,并且它的行名为test

定位网格项目可能会导致布局中出现空洞

正如您可能在之前的示例中看到的,基于行的定位会导致网格项目之间出现空隙。您可以通过将grid-auto-flow属性与dense值一起应用于网格容器来避免它们。

Comparing two grid layouts where the first contains gaps between items and the second has no gaps.
grid-auto-flow CSS 属性可以填充由基于行的定位引起的空隙。

堆叠网格项目

在网格中定位项目时,我们可以将它们堆叠或重叠在一起。这使我们能够将 CSS 网格用作绝对定位的替代方案。例如,我们可以在图像上放置一个字幕层,而无需使用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-column-start: 1;
  grid-column-end: -1;
  grid-row-start: 1;
  grid-row-end: -1;  
}

以下是我们得到的结果

Square photo of a cabin in the woods with a subtle fog behind it. A light gradient overlay is on top that goes from aqua to purple, and on top of that is a caption in white text.
使用 CSS 网格放置属性将元素堆叠在一起。

默认情况下,网格项目按源顺序堆叠,但您可以使用z-index属性控制它们的层级。在下面的例子中,我们重叠了一些项目,并且我们使用z-index属性将第二个项目提升到最高层级

.item:nth-child(2) {
  grid-row-start: 2;
  grid-row-end: 4;
  grid-column-start: 2;
  grid-column-end: 4;
  z-index: 1;
}
A grid of four numbered overlapping rectangles flowing from the top-left of the container to the bottom-right. The second item is on top of the stack.
使用z-index CSS 属性将第二个网格项目提升到堆栈顶部。

使用负索引以获得更多灵活性

在某些情况下,您希望网格中有一个全高项目,这意味着它从第一条网格线开始,到最后一条网格线结束。例如,在四行网格中,结束行索引为5,因此您可以编写以下代码以获得全高项目。

.grid-container {
  display: grid;
  grid-template-rows: repeat(4, min-content);
}

.grid-item.full-height {
  grid-row-start: 1;
  grid-row-end: 5;
}

它运行良好,但是如果行数更改为六行怎么办?在这种情况下,我们需要更新放置属性的索引值。

.grid-container {
  display: grid;
  grid-template-rows: repeat(5, min-content);
}

.grid-item.full-height {
  grid-row-start: 1;
  grid-row-end: 6;
}

但是,更灵活的解决方案是使用负索引!

.grid-item.full-height {
  grid-row-start: 1;
  grid-row-end: -1;
}

现在,具有.full-height类的网格项目始终跨越网格,无论我们在网格容器中添加或删除多少行。

命名区域优先于命名线

如果命名网格区域线名称相同,放置算法将优先使用命名网格区域的线。

考虑以下示例

.grid {
  display: grid;
  grid-template-rows: 80px [y] 80px 80px 80px 80px;
  grid-template-areas: 
    "x"
    "x"
    "x"
    "y"
    "y";
}

第二条网格线名为y,最后两行被定义为具有相同名称的区域。现在,为了定位第一个网格项目,我们将y分配为grid-row-end的值。让我们看看它将引用哪条线

.grid-item:first-child {
  grid-row-end: y;
}

正如您在下一张图片中看到的,虽然y线更靠近第一个项目,但浏览器选择了网格区域的边缘来放置项目的结束边缘。

Single column grid with five rows. The first item is green and positioned in the last row.
网格区域和网格线具有相同的名称 y,浏览器在将该名称分配给网格放置属性时选择网格区域线而不是命名网格线。

请注意,如果您使用网格区域的隐式名称线,则不适用此规则。例如,让我们将上一个示例中的网格线名称更改为y-end。另外,我们知道名为y的区域具有分配的y-end隐式网格线。现在,如果我们将y-end设置为grid-row-end,则网格命名线将成为这次的获胜者。

.grid {
  display: grid;
  grid-template-rows: 50px [y-end] 50px 50px 50px 50px;
  grid-template-areas: 
    "x"
    "x"
    "x"
    "y"
    "y";
}

.grid-item:first-child {
  grid-row-end: y-end;
}
A single column layout with five rows. The first item is in the first row and colored green.
网格区域和网格线共享相同的名称y。浏览器在将该名称分配给网格放置属性时选择网格区域线而不是命名网格线。

无障碍

使用网格布局属性时需要注意的一点是,重新排列项目会导致问题。当您更改项目的顺序时,只会更改网格项目的视觉顺序,而该顺序可能与原始文档顺序不同。对于使用键盘在文档中进行制表操作,或使用按照 HTML 顺序读取内容的屏幕阅读器的人来说,这可能会造成非常糟糕的体验。

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

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

演示

您可以更改演示中网格布局属性的值,以查看对第三个网格项目的影响

浏览器支持

更多信息