这是对 Michael_B already said 的扩展,以突出显示隐式网格线的创建方式。
让我们从一个简单的例子开始:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header;
background: blue;
}
<div class="container">
<header>H</header>
</div>
我们有一个网格项,我们只设置了grid-row-start,最终结果是两行,其中一行是空的。两者都在隐式网格中,因为我们没有定义任何显式网格。
要了解发生了什么,让我们参考the specification:
grid-template-rows、grid-template-columns 和 grid-template-areas 这三个属性共同定义了网格容器的显式网格。 ... 如果这些属性没有定义任何显式轨迹,显式网格仍然在每个轴上包含一条网格线。 ref
所以即使我们什么都不定义,我们仍然有一个明确的两线网格。这非常重要,因为没有这些行,我们就没有空行。
现在解释grid-row-start:header的部分:
<custom-ident>
第一次尝试将网格区域的边缘与命名网格区域匹配:如果存在名称为 ''-start (for grid--start) / -end'' (for grid--end),将第一条这样的行贡献给网格项的位置。
否则,将其视为整数 1 已与 <custom-ident> 一起指定。
很明显,我们会陷入否则并且会有grid-row-start:header 1:
<integer> && <custom-ident>?
将第N条网格线贡献给网格项的放置...
如果名称以<custom-ident> 的形式给出,则仅计算具有该名称的行。如果没有存在足够多的具有该名称的线,则假定所有隐式网格线都具有该名称以找到该位置。
在我们的例子中,我们没有足够的具有该名称的行(我们根本没有任何行)所以我们应该添加至少一行具有该名称并尝试放置我们的元素,因为整数是肯定的,该项目将被放置在该行下方:
网格有一条默认线(红色的),header 的使用会在其下方生成一个新的隐式线(由于自动添加了默认值1),并且元素将放置在该线下方创建多出一行。
如果我们使用-1,最后只有一行:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header -1;
background: blue;
}
<div class="container">
<header>H</header>
</div>
在这种情况下,隐式行在显式行上方生成,而我们的元素放置在两行之间。
如果给定一个负整数,它会从显式网格的末端边缘开始反向计数。
同时使用-1和1会给我们以下结果:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header -1;
background: blue;
}
footer {
grid-row-start: header 1;
background: red;
}
<div class="container">
<header>H</header>
<footer>F</footer>
</div>
这是另一个包含多个项目的示例,以说明 所有隐式网格线都假定具有该名称。
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header 1;
background: blue;
}
main {
grid-row-start: main 1;
background: red;
}
footer {
grid-row-start: footer -1;
background: green;
}
extra {
grid-row-start: extra 5;
background: orange;
}
<div class="container">
<header>H</header>
<main>M</main>
<footer>F</footer>
<extra>E</extra>
</div>
在这个例子中,我们总共需要 6 行隐式行,因为所有使用的整数都在 [-1,5] 范围内(不包括无效值 0),并且,为了放置每个元素,所有这些行都将具有为每个元素定义的名称。这就是为什么具有相同编号的两个元素将位于同一行(如 main 和 header),因为即使名称不同,参考行也会相同。
现在让我们在前面的示例中添加grid-row-end:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header;
grid-row-end: header;
background: blue;
}
<div class="container">
<header>H</header>
</div>
什么都不会发生,并且会产生完全相同的结果,因为:
如果起始行等于结束行,则删除结束行。 ref
我们换个名字吧:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header;
grid-row-end: foo;
background: blue;
}
<div class="container">
<header>H</header>
</div>
仍然是相同的结果,因为两者仍然相等(是的,它们相等!)。这两个值都将等于<name> 1,因此它们都只需要一个隐式行。然后浏览器将创建一个具有两个不同名称的隐式行,从而使我们的值相等。
让我们改变一个的值:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: header 1;
grid-row-end: foo 2;
background: blue;
}
<div class="container">
<header>H</header>
</div>
同样的结果,但使用“不同”的代码。在这种情况下,我们将有 2 条隐式线,我们的元素将放置在它们之间。
当涉及到隐式网格时,这个名称基本上是不相关的,因为它们都将共享相同的行。只有当我们在显式网格中定义它们时才有意义:
.container {
width:100px;
display: inline-grid;
grid-auto-rows: 40px;
border: 1px solid;
}
header {
grid-row-start: hello 1;
grid-row-end: john 3;
background: blue;
}
main {
grid-row-start: main 1;
grid-row-end: hi 2;
background: red;
}
footer {
grid-row-start: footer 2;
grid-row-end: custom 5;
background: green;
}
extra {
grid-row-start: extra 3;
grid-row-end: fsdfsdfsdfsd 5;
background: orange;
}
<div class="container">
<header>H</header>
<main>M</main>
<footer>F</footer>
<extra>E</extra>
</div>
在上面的例子中,你可以用任何随机字符串更新名字,你总是会得到相同的结果;它只取决于整数:
考虑到grid-column-*,上述所有行为在逻辑上都是相同的。
现在,我们拥有了解初始示例所发生的一切所需的一切。
首先我们有如下的显式网格:
body {
display: grid;
grid-template-areas:
"header"
"footer";
/* No relevant but to better illustrate*/
grid-auto-rows:50px;
grid-auto-columns:50px;
}
header {
grid-area: header;
background: lightblue;
}
/*main {
grid-area: main;
background: darkorange;
}*/
footer {
grid-area: footer;
background: blue;
}
<header>Header</header>
<!--<main>Main</main>-->
<footer>Footer</footer>
grid-template-areas 属性从模板中的命名网格区域创建隐式命名线。对于每个命名网格区域 foo,创建四个隐式命名行:两个命名为foo-start,命名命名网格区域的行开始和列开始行,两个命名为foo-end,命名行结束和列- 命名网格区域的结束线。 ref
现在如果我们用grid-area:main;添加第三个元素,这意味着我们有
grid-row-start:main 1;
grid-row-end:main 1;
grid-column-start:main 1;
grid-column-end:main 1;
我们删除了*-end,因为它们等于*-start
grid-row-start:main 1
grid-column-start:main 1
根据前面的解释,我们需要一个额外的隐式行main,我们的元素将被放置在水平元素的下方和垂直元素的右侧:
body {
display: grid;
grid-template-areas:
"header"
"footer";
/* No relevant but to better illustrate*/
grid-auto-rows:50px;
grid-auto-columns:50px;
}
header {
grid-area: header;
background: lightblue;
}
main {
grid-area: main;
background: darkorange;
}
footer {
grid-area: footer;
background: blue;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
如果我们删除grid-auto-*,行将是其内容的高度,使footer-end 和main 之间的行为空。该列将分割网格元素的宽度,网格元素是一个具有全宽的块元素。这就是为什么您只看到一个额外的列而不是额外的行:
body {
display: grid;
grid-template-areas:
"header"
"footer";
}
header {
grid-area: header;
background: lightblue;
}
main {
grid-area: main;
background: darkorange;
}
footer {
grid-area: footer;
background: blue;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
另一个有趣的观察是,如果您使用grid-area:<name> 添加更多元素,它们将全部位于彼此之上:
body {
display: grid;
grid-template-areas:
"header"
"footer";
}
header {
grid-area: header;
background: lightblue;
}
main {
grid-area: main;
background: darkorange;
}
footer {
grid-area: footer;
background: blue;
}
extra {
grid-area: extra;
background: red;
opacity:0.8;
}
more {
grid-area: more;
background: green;
opacity:0.3;
}
<header>Header</header>
<main>Main</main>
<footer>Footer</footer>
<extra>E</extra>
<more>More</more>
根据前面的解释,他们都会有以下几点:
grid-row-start:<name> 1;
grid-column-start:<name> 1;
由于编号相同(名称与我们已经解释的无关)它们都属于同一区域。