DigitalOcean 为您的旅程各个阶段提供云产品。立即开始使用 $200 免费额度!
grid-template-rows
CSS 属性是 CSS 网格布局规范 的一部分,通过指定网格轨道的大小及其行名称来定义 网格容器 的行。
.app-layout {
display: grid;
grid-template-rows: auto 1fr auto;
}

在我们深入了解 grid-template-rows
属性之前,有一点需要说明,那就是网格线和网格轨道之间的区别。网格线指的是定义网格列和行的线的名称。网格轨道指的是网格线之间空间的长度。
语法
grid-template-rows: none | <track-list> | <auto-track-list> | subgrid <line-name-list>?
完整定义
where:
<track-list> = [ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>?
<auto-track-list> = [ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>? <auto-repeat>
[ <line-names>? [ <fixed-size> | <fixed-repeat> ] ]* <line-names>?
<line-name-list> = [ <line-names> | <name-repeat> ]+
where:
<line-names> = '[' <custom-ident>* ']'
<track-size> = <track-breadth> | minmax( <inflexible-breadth> , <track-breadth> ) | fit-content( [ <length> | <percentage> ] )
<track-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <track-size> ]+ <line-names>? )
<fixed-size> = <fixed-breadth> | minmax( <fixed-breadth> , <track-breadth> ) | minmax( <inflexible-breadth> , <fixed-breadth> )
<fixed-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
<auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
where:
<track-breadth> = <length-percentage> | <flex> | min-content | max-content | auto
<inflexible-breadth> = <length> | <percentage> | min-content | max-content | auto
<fixed-breadth> = <length-percentage>
- 初始值:
none
- 应用于: 网格容器
- 继承: 否
- 计算值:按指定值,但将相对长度转换为绝对长度
- 动画类型: 简单列表,包含长度、百分比或 calc,前提是列表中唯一的区别是长度、百分比或 calc 组件的值。
值
/* Keyword value */
grid-template-rows: none;
/* <track-list> values */
grid-template-rows: 200px 1fr 180px;
grid-template-rows: [linename col1] 250px [line2];
grid-template-rows: [sidebar] 1fr [content] 2fr;
grid-template-rows: fit-content(50%);
grid-template-rows: minmax(200px, 1fr) minmax(100px, 1fr);
grid-template-rows: repeat(4, 1fr);
grid-template-rows: subgrid;
grid-template-rows: masonry;
/* <auto-track-list> values */
grid-template-rows: 100px repeat(auto-fill, 100px) 200px;
grid-template-rows: 100px repeat(2, 1fr auto) 200px repeat(3, 5fr);
grid-template-rows: minmax(150px, max-content) repeat(auto-fill, 180px) 15%;
grid-template-rows: [col1] 100px [col1-end] repeat(auto-fit, [line3] 400px);
/* Global values */
grid-template-rows: inherit;
grid-template-rows: initial; /* same as `none` */
grid-template-rows: revert;
grid-template-rows: unset;
none
这是默认值。使用 none
值意味着 grid-template-rows
不生成任何显式网格轨道,这反过来意味着行是隐式生成的(即在您无需显式定义的情况下为您创建),并且轨道大小由 grid-auto-rows
属性定义。
请注意,grid-template-rows
不是创建显式网格行轨道的唯一方法。还可以使用 grid-template-areas
属性来完成,该属性允许使用自定义名称(例如 sidebar
、main
等)来定义网格区域。
隐式网格和显式网格之间的区别在 Manuel Matuzovic 的这篇博文中 有很好的总结。
<length>
此值可以是任何有效的非负 CSS 长度,例如 px
、em
和 rem
等,用于指定行的轨道大小(即高度)。
<percentage>
这是一个相对于网格容器内联大小的非负值。如果网格容器的大小取决于其轨道的尺寸,则百分比必须与声明 auto
相同对待。
使用百分比值的一个缺点是,如果您在轨道之间添加了 间隙,间隙的大小将被添加到轨道的尺寸中,这 可能会导致溢出。请使用 fr
单位 或 auto
关键字来调整轨道大小,并防止这种情况发生。
<flex>
这是一个用 fr
单位表示的非负值,它允许您通过将轨道的尺寸指定为网格容器中可用空间的一部分来创建灵活的网格轨道。这样,当网格高度发生变化时,行也会随之发生变化,从而形成更具响应性的网格。
例如,考虑一个高度为 900px
的三行网格容器。假设第一行(顶部)的高度是固定的(即不会改变)为 300px
,而第二行占一个分数单位(1fr
),第三行占两个分数单位(2fr
)。
.grid {
display: grid;
height: 900px;
grid-template-rows: 300px 1fr 2fr;
}
后两行是分数行,因此它们将占用任何剩余的可用空间。在这种情况下,可用空间是第一行的固定 300px
高度被占用后剩余的空间。之后,后两行将根据它们获得的分数数量来分配剩余的空间。
在此示例中,剩余的可用空间为 600px
(即 900px
减去 300px
)。第二行获得该空间的一个分数(1fr
),而第三行获得两个分数(2fr
)。让我们简单地计算一下 600px
的一个分数的高度。
1fr = ([Grid Container Height] - [Fixed Row Height]) / [Sum of the flex factors]
1fr = (900px - 300px) / 3
1fr = 600px / 3
1fr = 200px
啊哈!一个分数是 200px
。由于第二行是 1fr
,因此它也必须是 200px
。这使得我们剩余了 400px
的可用空间(900px
– 300px
– 200px
),这恰好是第二行大小的两倍。
但是等等!还有更多。
请记住,网格在计算有多少可用空间分配给分数行时,会考虑网格轨道之间添加的任何间隙。当然,这里的好处是,我们的行永远不会溢出网格容器。
让我们在前面的示例中添加一个间隙
.grid {
display: grid;
height: 900px;
grid-template-rows: 300px 1fr 2fr;
gap: 15px;
}
即使我们在这里只声明了一个间隙,但实际上它就像我们声明了两个间隙。这是因为每行之间都有一个 15px
的间隙(一行在行 1 和行 2 之间,另一行在行 2 和行 3 之间)。这意味着我们的网格中共有 30px
的间隙需要计入可用空间。
1fr = ([Grid Container Height] - [Gaps] - [Fixed Row Height]) / [Sum of the flex factors]
1fr = (900px - 30px - 300px) / 3
1fr = 570px / 3
1fr = 190px
我不知道你怎么样,但我不想做太多手动计算。这就是 CSS 网格的强大之处——它会处理所有这些!
minmax(min, max)
minmax()
函数接受两个参数:最小长度值和最大长度值。它告诉网格容器,grid-template-rows
的高度不能小于最小值,但不能大于最大值。 我们关于 CSS 函数的指南更全面地解释了该函数的工作原理。
请看以下示例
grid-template-rows: 200px minmax(100px, 400px);
这里有两行:一行高度为 200px
,另一行表示为 minmax(100px, 400px)
。看起来很奇怪,对吧?但这只是说第二行必须占用至少 100px
的空间,但不能超过 400px
。
更明确地说:只要可用空间大于 100px
,第二行就可以扩展到 400px
,但必须停止在那里。否则,行的高度为 100px
。
min
和 max
参数接受以下所有值,但 min
值不能是 flex 值(例如 1fr
)。
<length-percentage> | <flex> | min-content | max-content | auto
因此,由于min
值为弹性值,所以这是无效的。
/* 👎 */
grid-template-rows: minmax(1fr, 500px) 3fr;
但这些完全有效
/* 👍 */
grid-template-rows: minmax(auto, 1fr) 3fr;
grid-template-rows: minmax(200%, 1fr) 1fr;
auto
在大多数情况下,auto
关键字的行为类似于minmax(min-content,
max-content)
。
由于auto
轨道大小可以被align-content
和justify-content
属性拉伸,因此它们将默认情况下自动占用网格容器中任何剩余的空间。也就是说,在分配剩余空间时,auto
轨道大小无法与fr
单位抗衡——它们会调整到其内容的最大尺寸。
看看这两个轨道示例的结果
grid-template-rows: auto auto auto;
grid-template-rows: auto 1fr auto;
当所有三行都设置为auto
(我们也可以写成repeat(3, auto)
——但稍后会详细介绍)时,它们所做的只是共享相等的空间。但是,当我们在中间作为第二行放下一个分数单位时,auto
行只与它们内部的内容一样高,而1fr
行则占据了剩余的空间。

fr
单位与自动轨道并排的行为min-content
min-content
关键字表示元素在网格容器中不溢出其内容的情况下可能占用的最小空间量。内容可以是文本、图像或视频。
假设内容是“CSS is awesome”,以垂直模式编写,则min-content
是“awesome”一词的宽度,因为这是内容中最宽的部分(比“CSS”和“is”更宽)。如果行变得更窄,则文本将开始溢出容器。
在代码中,它看起来像这样
.grid {
display: grid;
grid-template-rows: min-content 1fr;
gap: 1rem;
}
.grid-item {
writing-mode: vertical-rl;
}
…这将导致类似于这样的结果

min-content
关键字在网格布局中的行为max-content
max-content
关键字表示元素适合所有内容而不被包装或溢出所需的最小尺寸。包含“max”的名称听起来像是我们正在处理最大尺寸,因此此值可能有点令人费解。
如果我们重新审视上面的min-content
示例,则具有max-content
大小值的网格轨道将增长,直到其内容可以容纳在一行中。因此,在“CSS is awesome”的情况下,max-content
是这三个单词在一行上占用的空间。
.grid {
display: grid;
grid-template-rows: max-content 1fr;
gap: 1rem;
}

max-content
关键字在网格布局中的行为fit-content( <length-percentage> )
fit-content()
函数(在我们的CSS函数指南中有一个详细的解释)使用可用的空间以及接受percentage
或length
值作为网格轨道允许的最大尺寸,同时确保轨道永远不会超过max-content
,并且永远不会缩小到最小值。最小值通常(但不总是)等于min-content
。
.grid {
display: grid;
grid-template-rows: fit-content(400px) fit-content(400px) 1fr;
gap: 1rem;
}
在下图中,第一行不会扩展到超过其max-content
大小(即“fit-content(400px)”单词在一行上的宽度)——它只延伸以适合其内容。但是,第二行包含更多内容,并且在达到400px
的高度时停止拉伸,这是设置给函数的限制。

400px
。如果它可以在该限制内容纳所有内容,那就太好了,在max-content
处停止。否则,显示尽可能多的内容,直到400px
,然后开始分解成额外的行。[linename]
虽然网格线始终可以通过隐式数字名称来引用,但我们也可以为它们赋予自定义名称,以使代码在更复杂的网格中更容易理解。然后,可以在通过行名定位网格项时引用每个行名。
网格线可以通过在方括号中添加名称并将每个名称用空格隔开来拥有多个名称。
grid-template-rows: [first header-start] 100px [header-end content-start] 1fr [lastline];

请注意,行名是<custom-ident>
,这是一种通用数据类型,表示任何有效的 CSS 标识符,不会被误解为该属性值定义中的预定义关键字。因此,我们可以将一行命名为super-awesome-spider-monkey
,只要它不包含可能导致冲突的全局 CSS 值,例如span
、auto
、inherit
、initial
等等。
此外,此类标识符是完全区分大小写的。例如,CSS 将sidebar-end
和Sidebar-Name
视为两个完全不同的、无关的行名。此外,行名可以通过grid-template-rows
属性显式分配,或通过grid-template-areas
属性的命名网格区域隐式分配。
repeat([ <positive-integer> | auto-fill | auto-fit ] , <track-list>)
repeat()
函数是定义grid-template-rows
的一种高效方法,当行相同的时候。该函数接收行数,然后是行大小。
/* Writing this */
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
/* is the same as this: */
grid-template-rows: repeat(5, 1fr);
另一个例子,这次来自规范
grid-template-rows: 10px [row-start] 250px [row-end]
10px [row-start] 250px [row-end]
10px [row-start] 250px [row-end]
10px [row-start] 250px [row-end] 10px;
/* same as above, except easier to write */
grid-template-rows: repeat(4, 10px [row-start] 250px [row-end]) 10px;
auto-fill
和auto-fit
除了显示重复次数的整数之外,还允许将auto-fill
和auto-fit
这两个关键字用作repeat()
函数的第一个参数。
这些关键字更适合列轨道而不是行轨道,但让我们看看它们应用于grid-template-rows
时的行为。
当auto-fill
和auto-fit
用作重复次数,并且如果网格容器具有确定的高度或最大高度,则重复次数是不导致网格溢出其网格容器内容框的最大可能整数;如果任何重复次数都会溢出,则只有一次重复。
另一方面,如果网格容器具有确定的最小高度,则重复次数是最小可能的整数,它满足该最小要求。否则,指定的轨道列表只重复一次。
正如您在以下示例中看到的,如果没有为网格容器定义显式高度,则这些关键字只应用于第一行轨道;否则,它们应用于适合显式高度的最大行数,而溢出的行将具有auto
大小。


在使用repeat()
函数时,有一些限制值得注意。
- 它无法在
repeat()
函数中嵌套repeat()
函数。
/* This is invalid */
grid-template-rows: repeat(4, 1fr repeat(5, 1fr));
- 在使用
auto-fill
或auto-fit
时,它不接受内在或弹性长度值(例如fr
单位)。它只接受显式轨道大小,以便能够计算出进入网格容器的行数。
/* This is invalid */
grid-template-rows: repeat(auto-fit, 1fr);
- 然而,只要第一个值是正数,就可以使用内在或弹性大小作为函数的第二个值。
/* These are invalid */
grid-template-rows: repeat(auto-fit, 1fr);
grid-template-rows: repeat(min-content, 1fr);
/* This is valid */
grid-template-rows: repeat(6, 1fr);
- 在使用
auto-fill
或auto-fit
时,它只能在grid-template-rows
轨道列表中使用一次。但是,只要第二个值是固定的,我们就可以使用多个repeat()
函数。
/* These are invalid */
grid-template-rows: repeat(auto-fill, minmax(10rem, 1fr)) 100px repeat(auto-fill, minmax(5rem, auto));
grid-template-rows: repeat(auto-fill, minmax(10rem, 1fr)) 100px repeat(3, 1fr);
/* This is valid */
grid-template-rows: repeat(auto-fill, minmax(10rem, 1fr)) 100px repeat(3, 200px);
subgrid
我们可以在网格内拥有网格吗?当然可以!这要归功于subgrid
关键字值。声明它允许内部(子)网格共享外部(父)网格的轨道线,从而实现更一致的轨道线,而不必重新声明它们。
Subgrid 被认为是实验性的,在撰写本文时仅在 Firefox 中受支持。
因此,假设我们在网格中嵌套了网格。
.grid-container {
display: grid;
grid-template-rows: repeat(4, 1fr);
}
.grid-container .grid-item {
display: grid;
}
我们可以将嵌套的网格变成subgrid
,以与父网格共享轨道线。
.grid-container {
display: grid;
grid-template-rows: repeat(4, 1fr);
gap: 1rem;
}
.grid-container .grid-item {
display: grid;
grid-template-rows: subgrid;
}
现在,子网格的项目将根据主网格容器的轨道大小进行放置和调整大小。例如,考虑以下 HTML。
<div class="grid">
<div class="item"></div>
<div class="item subgrid">
<div class="subitem"></div>
<div class="subitem"></div>
</div>
<div class="item"></div>
<div class="item"></div>
</div>
现在让我们创建一个子网格。
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr); /* Establish a grid with 4 columns */
grid-template-rows: repeat(4, 1fr); /* Establish a grid with 4 rows */
}
.item {
grid-row: 1/-1; /* Make all items as tall as the 4 tracks */
}
.subgrid {
display: grid;
grid-template-rows: subgrid;
grid-row: 3/-1; /* Make the subgrid item size, half of the other items */
}
在这里你可以看到子网格项目会根据父网格的轨道大小进行调整。

子网格中的间隙会由父网格继承,但是可以在子网格元素上使用不同的gap
值覆盖它。
.grid-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(4, 1fr);
gap: 1rem; /* This is inherited by the child grid */
}
.grid-container .grid-item {
display: grid;
grid-template-rows: subgrid;
gap: 0.5rem; /* This overrides the parent grid's gap */
}
子网格有它自己的行号。例如,当你在子网格中使用行号1
时,它指向的是子网格的第一行,而不是父网格。因此,即使子网格从父网格的第三条轨道线上开始,子网格的第一条轨道线仍然是1
,而不是3
。
当然,我们可以在子网格中声明自定义网格线名称。
.grid-container .grid-item {
display: grid;
grid-template-rows: subgrid [header-start] [header-end] [main-start] [main-last];
}
哦,我们也可以在这里完全使用repeat()
函数来指定轨道线名称。
.grid-container .grid-item {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: subgrid repeat(2, [a] 1fr [b]);
}
不过要注意的是,repeat()
函数会合并任何相邻的轨道线名称。
/* These are equivalent */
grid-template-rows: repeat(2, [a] 1fr [b]);
grid-template-rows: [a] 1fr [b a] 1fr [b];
请注意,在子网格中,该维度上不能有任何隐式轨道。因此,如果你添加更多网格项目,它们将被放置在子网格的现有显式轨道中。例如,在前面示例的子网格中添加一个子元素,该子元素将被放置在最后一个轨道的下方。
此浏览器支持数据来自Caniuse,其中包含更多详细信息。数字表示浏览器从该版本开始支持该功能。
桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
117 | 71 | 否 | 117 | 16.0 |
移动设备/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
127 | 127 | 127 | 16.0 |
masonry
你知道我们所说的masonry是什么吗?它是一种很酷的布局,其中网格中的项目会根据列中可用的垂直空间进行平铺和拼接。它在几年前由David DeSandro 的同名 JavaScript 库推广开来。

感谢 CSS Grid,我们将能够在不使用 JavaScript 的情况下实现砖砌布局。然而,在撰写本文时,它仍然是CSS Grid 规范第 3 级的一部分,目前处于编辑草案阶段。但是,它在 Firefox 中可以使用,不过需要启用一个标志。

我们可能会在规范实际发布之前看到一些更改。但以下是目前的样子。
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
}
示例
耶,演示时间到了!我有一些示例展示了grid-template-rows
属性的功能,你在使用 CSS Grid 布局时可能会遇到它。
应用程序布局
可以使用以下 CSS 实现一个简单的应用程序布局。
.layout {
display: grid;
grid-template-rows: min-content 1fr min-content;
}
侧边栏菜单
砖砌
浏览器支持
更多信息
- CSS Grid 布局模块第 2 级(介绍了
subgrid
) - CSS Grid 布局模块第 3 级(介绍了
masonry
值) - CSS Grid 的完整指南(CSS-Tricks)
- 显式网格和隐式网格的区别(Manuel Matuzovic)
相关技巧!
使用 CSS 计数器和 CSS 网格进行计数
使用 CSS Grid 进行布局
使用 CSS 网格构建会议日程
CSS 网格中可展开的区域
将 Position Sticky 与 CSS 网格一起使用
六边形及其他:灵活的响应式网格模式,无需媒体查询
相关
align-content
.element { align-content: space-around; }
display
.element { display: inline-block; }
gap
.element { gap: 20px 30px; }
grid-template-areas
.element { grid-template-areas: "header header" "sidebar main"; }
grid-template-columns
.element { grid-template-columns: 300px 1fr; }
justify-content
.element { justify-content: center; }
row-gap
.element { row-gap: 2rem; }