Hello ,CSS Grid
之前在项目中做一个分块展示页面,其页面布局大致如图所示:
遇到这样的布局,在不考虑浏览器兼容性的情况下,笔者认为使用Grid布局应该是一种很不错的选择 —— 容器元素间没有太深的层级关系,且容器外观大致相似。在此第一次尝试了Grid布局方式。
Grid 布局简介
Grid布局是目前(2020年5月文章撰写时,虽然两三年前Google浏览器就能使用了)较新的一种布局方式,可以使得网页上的元素以较为简便的方式在页面横向和纵向上进行排布。
Grid布局是一种二维布局的方式。这一点和多年前盛行的表格布局相似,但比表格布局更加轻量、更加灵活、可访问性更强、布局更快。Flex以及 Inline-block / Float 等一维布局方式,在同一容器中排布元素时,仅能够在一个方向上排列 —— 要么行,要么列;如需转换排列方向,则需要在容器下再嵌套容器,在新的容器中排列。而如果使用 Grid 布局,容器元素嵌套层级更少。仅需一个外部的 Grid 容器与若干个位于内部的子元素,即可对子元素实现“扁平化”管理。
……好了,以上是笔者自己的介绍和看法,不一定权威。以下是一些参考链接:
CSS Grid Layout - CSS: Cascading Style Sheets | MDN
想要以游戏的方式来了解CSS Grid布局?或许可以看看:Grid Garden - A game for learning CSS grid
简易Demo
你可以通过该Demo,快速了解CSS Grid布局的用途、使用方式,同时也为我们下方的其他讲解打个基础。
- HTML结构
<!--
重点关注:grid-cell元素上内联的grid-area属性。
-->
<div class="grid-wrap">
<section class="grid-cell" style="grid-area:cell1">1</section>
<section class="grid-cell" style="grid-area:cell2">2</section>
<section class="grid-cell" style="grid-area:cell3">3</section>
<section class="grid-cell" style="grid-area:cell4">4</section>
<section class="grid-cell" style="grid-area:cell5">5</section>
</div>
外层grid-wrap
是网格容器,其下直接包含了所有的子元素。
我们需要为每一个子元素指定一个grid-area属性,标识该子元素将会使用网格容器中的哪块区域。这里的属性值是一个自定义字符串。
- CSS规则定义
/* 网格容器 */
/* 重点关注
display
grid-template-areas
grid-template-columns
grid-template-rows
*/
.grid-wrap {
height: 100%;
display: grid;
box-sizing: border-box;
padding: 30px 0;
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5';
grid-template-columns: 50% 50%;
grid-template-rows: 25% 25% 50%;
}
/* 网格子元素 - 仅仅用于美化,无重要代码 */
.grid-cell {
display: flex;
align-items: center;
justify-content: center;
background-color: rgb(0,91,151);
background-image: linear-gradient( -30deg, rgb(46,49,146) 0%, rgb(30,156,215) 39.4%, rgb(0,113,188) 72.16%, rgb(0,91,151) 100% );
margin: 15px 25px;
border-radius: 40px;
color: #fff;
text-align: center;
font-size: 5em
}
在此我们看一下网格容器(.grid-wrap
)的样式。这里有几个之前没用过的属性:
display: grid;
将容器配置为grid容器grid-template-areas: 'cell1 cell3' 'cell1 cell4' 'cell2 cell5';
配置容器布局,此处布局为三行二列布局。这样看会更好理解一些:
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5'
;
在这里,我们将网格容器下的子元素按照这一布局进行放置,具体出现的位置由子元素各自设定的grid-area
决定。
- grid-template-columns: 50% 50%; 配置容器每列列宽。
- grid-template-rows: 25% 25% 50%; 配置容器每行行高。
同时我们看一下网格子元素(.grid-cell
)的样式,这里有个早前未使用过的属性:
- grid-area:cell1;
用于配置子元素在网格中的位置,此处简易Demo,属性值来自于父元素
grid-template-areas
定义的区域。该属性可以设置的值较为灵活,并非此处如此处Demo这么简单,详见下方。
以上内容就是简易Demo的全部相关讲解,个人认为这一简易Demo大致上可以应付日常业务上所遇到的一些需求不高的布局,到此你对CSS Grid布局方式应该已经有了一个简单的印象。有关CSS Grid布局的更多细节,请继续阅读下文。
相关术语
文章写作过程中,笔者发现自己对一些内容的介绍用词并不是很准确,因此参照MDN的介绍整理了一下表格布局的相关术语,调整了措辞。
- 网格 display值为grid的元素。在下文中被笔者称为"网格容器"。
- 网格线
网格线是网格中每行、每列的分割线,从每行 / 每列的第一个元素起始的那根线算起,到最后一个元素终止的那根线结束。网格中第一根网格线索引记为
1
(注意不是0
)。 - 网格轨道 网格线与网格线之间的部分,即网格行、网格列的合称。
- 网格单元 两根相邻行网格线与两根相邻列网格线之间交叉形成的区域(类比“井”字中间的部分)。
- 网格区域 网格区域是由一个或多个网格单元组成的一块矩形区域 —— 非矩形区域是无效的。
- 间距 相邻两个网格轨道之间的空隙,类比两个元素间不发生合并的margin。
- 网格轴 网格的横轴、纵轴。
- 网格行 网格中的水平轨道。
- 网格列 网格中的垂直轨道。
通过网格容器设置子元素相关属性
这一章节,我们将为网格容器(display:grid
)设置一些属性,来控制子元素的尺寸、间距等样式。
这里介绍的一些特性包括:
-
控制尺寸与位置
grid-template-areas
属性grid-template-columns
、grid-template-rows
属性grid-template
属性repeat()
函数minmax()
函数fr
单位grid-auto-rows
、grid-auto-columns
属性grid-auto-flow
属性
-
控制间距
grid-row-gap
、grid-column-gap
属性grid-gap
/gap
属性
确定子元素的位置、尺寸
设置子元素的位置
首先我们来看看Grid布局如何对子元素的位置进行确定。在这里我们使用的是grid-template-areas
属性。
在使用grid-template-areas
之前,首先我们需要为Grid的子元素设置grid-area
属性,上方例子有5个子元素,我们分别将它们标识为cell1
、cell2
、cell3
、cell4
、cell5
。这里相当于为这5个子元素命名,以供grid-template-areas
使用。
接下来我们就可以在grid-template-areas
中,使用这些元素的grid-area
属性,来为这些元素布局 。
grid-template-areas
属性定义了一个网格区域模板,描述了网格容器中各个网格区域的位置。子元素最终将根据这些网格区域进行定位。
我们来看一看上一节中的例子:
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5'
;
此处美化了一下代码,可以看到我们为网格设置了一个三行二列布局。
浏览器会自动检查grid-template-areas
属性是否存在可以合并的网格单元。若某几个网格单元同名、连续且可以构成矩形,即可合并为一个网格区域。这里的2个名为cell1
的网格单元便满足了这个条件,因此被合并为了一个网格区域。
设置网格行、列尺寸
上一节中已经介绍了对网格行、列的尺寸进行设置的方式:
-
grid-template-columns
- 每一列的宽 -
grid-template-rows
- 每一行的高
这两个属性用于设置网格容器中各行、各列的宽与高。
默认情况下,倘若不对这两个属性进行设置,那么网格容器下各行、各列将会自动按照grid-template-areas
里设置的布局规则,平均分配网格容器的宽、高。
基本语法类似:
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5';
grid-template-columns: 50% 50%;
grid-template-rows: 25% 25% 50%;
此处百分比是相对于网格容器尺寸的百分比。除了百分比外,这里的单位还可以是px
、em
、vh
、vw
、pt
等等等等。
为了书写便捷,这两个属性还可接收一些关键字和函数。下面我们来换一个行列稍微多一些的例子来看一看这些关键字与函数的作用。
repeat()
函数 用于简化重复布局的写法。该函数接收两个参数,第一个是重复次数,第二个是网格行或列的尺寸,该尺寸可接收若干个,根据行或列的数量依次重复往下设置。如图:
grid-template-rows: repeat(3, 4em 10em);
grid-template-columns: repeat(2, 5em 30em);
相当于
grid-template-rows: 4em 10em 4em 10em 4em 10em;
grid-template-columns: 5em 30em 5em 30em;
fr
单位fr
意为fraction
,即“分数”,网格容器某一维度上的空间(或者说某一维度上固定空间分配完后剩余的空间)被平均分配后,这一维度上每一个轨道的宽度 / 高度相当于1fr
。该单位并不是一个确切的单位,主要用于表示网格在两个维度上的伸缩因数,似乎和Flex中的flex-shrink
、flex-grow
以及flex-basis
书写略有类似。 此处,使用fr
表示的尺寸可以与其它单位表示的尺寸一起使用。这些使用其它单位的尺寸被分配后,剩余的空间由使用fr
单位的尺寸来进行分配。如图所示:
grid-template-rows: 100px 1fr 2fr 3fr;
grid-template-columns: 100px minmax(1px,1fr) 2fr;
上图将网格的首行、首列设置为了100px
,其它行、列设为了以fr
为单位的值。我们可以发现以fr
为单位的网格,在两个维度上的比例关系满足我们为它们设置的值。
十分有趣的是,我们在这里将首行、首列在各自维度上的尺寸设为了固定值100px
,而其它网格(以fr
为单位的网格)尺寸则自动占满容器。此时若拖动改变窗口大小,可以发现首行首列在各自维度上尺寸是固定的,但是其他网格大小是自适应变化的 —— 这似乎是一个解决“如何实现左侧栏固定右侧栏自适应?”问题的新方案。
minmax()
函数 顾名思义,这一函数实际上就是用于将网格行、列的尺寸限制于某个范围之内,接收两个表示尺寸的参数。
经过笔者测试,第一个表示尺寸的参数(最小值),单位不能为fr
。fr
表示的是网格容器空间平均分配后一个网格轨道的宽度 / 高度,这个宽度 / 高度本身就是网格轨道的最大值,除非最终最小值大于这个值。
当容器某个维度尺寸过小、无法容纳网格轨道时,网格轨道在这一维度尺寸将会使用最小值,当容器很大时,若足以容纳网格轨道,则网格轨道将会使用最大值。
合并书写 grid-template
相关属性
grid-template
属性实际上是grid-template-areas
、grid-template-columns
、grid-template-rows
三个属性的简写。
我们可以尝试把这两个属性统一为grid-template
来进行书写,即:
- 原始CSS属性:
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5';
grid-template-columns: 50% 50%;
grid-template-rows: 25% 25% 50%;
- 合并
grid-template-rows
、grid-template-columns
到grid-template
并单独设置grid-template-areas
:
grid-template: 25% 25% 50% / 50% 50%;
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5';
此处将
grid-template-areas
属性写在了在后面 ——grid-template-areas
会被grid-template
中对应的空值覆盖。
- 再合并
grid-template-areas
到grid-template
grid-template:
'cell1 cell3' 25%
'cell1 cell4' 25%
'cell2 cell5' 50% /
50% 50%
这里使用grid-template
属性设置网格行高的时候,将每行高度写在了每行最后,所有行高定义完后,再以/
为分割,依次定义每列列宽;可以发现格式化后的grid-template
属性的写法能够更加直观地设置网格布局。
网格排满后,多余的元素如何放置?
在以上的网格布局 Demo 中,我们所设置的布局能够让所有子元素不多少、不包含空隙地占满所有网格区域。那么网格容器中找不到地方放置的多余子元素将会被如何处理呢? —— 难道直接舍弃?🥴
显然并不是这样。我们在上文fr
Demo中多加了一些子元素(10-16),但我们并没有为这些子元素设置任何区域,于是网格容器便新增一行,这些子元素将会被放入其中,并逐行向下排列。如图:
这里出现个问题:我们为“子元素1-9”设定了区域以及尺寸,但目前尺寸似乎与我们设置的尺寸不相符了 —— 除去以
px
为单位的区域尺寸,只看以fr
为单位的区域尺寸,这些区域对应的子元素行的尺寸比例应当满足1:2:3,列的比例应当满足1:2。新元素加入,产生新行后,这种比例不再正确。
吐个槽,经过测试,这问题是由gap
引起的;此处暂时把gap设为0。
如果要为这些新添加的、没有定义使用哪些区域的元素设置行高,我们可以在网格容器设置grid-auto-rows
:
grid-auto-rows: 50px 20px;
该属性可接受多个尺寸值,每多出一行就每使用一个值,循环使用。我们为网格容器增加更多子元素来查看这个效果:
相信你一定会有这个问题:如果我们不希望这些元素逐行向下排列,而是希望它们逐列向右排列,那我们要如何做呢?
这里,我们就需要来改变一下网格布局中布局未设置区域的子元素的流向了,使用grid-auto-flow
属性。该属性接受的参数包括row
与column
。
同时,我们需要将原先的grid-auto-rows
属性换为grid-auto-column
。最终CSS类似:
grid-auto-columns: 90px 60px;
grid-auto-flow: column;
见缝就插针的子元素
上面的Demo都没涉及到网格存在空白区域的情况,如下图:
我们删去了原本放在cell5
、cell6
、cell7
位置的子元素5-7,于是它们原本的位置就空出来了。
接下来我们在网格中继续插入的子元素(子元素10-13)—— 不指定grid-area
属性,则它们的位置由浏览器自动指定:
我们可以看到这些元素被自动插入了网格容器的空白网格单元中 —— 值的注意的是这里插入的是空白网格单元而非空白网格区域。因此在图上你可以看到位于"cell7"的子元素有子元素11、子元素13两个元素,而非仅有一个元素。
此时网格中就没有空位(空白网格单元)了,再插入新的子元素,子元素将发生如上文“网格排满后,多余的元素如何放置?”中所述的情况。
如果没有grid-template-areas
属性,网格容器中子元素将如何排布?
目前为止,除了上节“见缝就插针的子元素”未设置grid-area
的子元素外,我们所有子元素的布局都是依赖grid-template-areas
而进行的,如上文所言,这一属性定义了一个网格区域模板,子元素可以按照这一模板在容器中进行排布。那现在没有了这一模板,这些子元素将会怎样放置?
这里我们删除网格容器上的grid-template-areas
属性以及子元素上的grid-area
属性,同时为了让演示效果更加显著,这里增加了更多子元素,如图:
可以发现这里的布局是一个N行三列的布局 —— 准确来说是四行三列布局 —— 四行是由容器上grid-template-rows
的属性所设置的,只是子元素过多,多余的子元素被挤下去了; 三列则来自grid-template-columns
。
因此,由图上可知,如果没有grid-template-areas
属性,网格容器中子元素将从左到右,从上往下在各个网格单元中依次排列,类似这篇博客中的文字一样;若要改变排列方向,将网格容器grid-auto-flow
属性的默认值row
改为column
即可,如图:
在网格容器没有grid-template-areas
属性的情况下,为某个子元素的grid-area
设置一个网格区域名称将会发生什么?
此时,网格容器grid-template-areas
属性已经不存在,子元素找不到其中的区域,只好被放置到了容器包含固定行列部分外,位于右侧和下方分别新创建的两条轨道的外侧轨道上。
有趣的是,这里行、列两个维度分别被插入了两条新轨道 —— 为什么是两条?这是个问题。。。(此前笔者认为这里应该只会增加一个新轨道,看来这里又可以研究一阵了🥴)被设置网格区域的"子元素1"被放到了最外侧轨道。
但不管如何,既然创建了新轨道,那么其它子元素也会进入到新轨道,这使得网格容器内的布局发生了变化。如图:
我们可以再在网格容器下添加几个子元素,创建新行,可以发现“子元素1”并不会随之移动,而是固定在了原先在新轨道上的位置。如图:
设置子元素间距
平常在开发时,若要调整元素间的间隔,我们能想到的方法莫过于为每个子元素增加margin
值。类似:
不过缺点也显而易见。网格四周边缘的子元素也会应用这一margin
值,导致网格容器内部四周也会存在边距。倘若我们不希望存在这些边距,且不能够改变HTML结构,该如何做呢? —— 莫非为在边缘的元素一个个设置margin-top
/margin-right
/margin-bottom
/margin-left
?😫
在 CSS Grid布局中,有一个专门调整网格轨道之间间隔的属性,那就是grid-gap
(在Chrome 84下测试时发现该属性可再简写为gap
)。grid-gap
接受一个长度值,用于定义行列间距;同时也可以接受两个空格分隔的长度值,分别用于定义列间距和行间距 :
grid-gap: 0.5cm;
grid-gap
实际上是grid-row-gap
和grid-column-gap
两个属性的缩写,在这里相当于:
grid-row-gap: 0.5cm;
grid-column-gap: 0.5cm;
在下图中,我们将行与行之间的间距设为了10px
,列与列之间的间距设为了200px
。
grid-row-gap: 10px;
grid-column-gap: 200px;
通过Grid子元素设置子元素自身相关属性
这一章节,我们将为Grid容器下的子元素设置一些属性,来控制子元素自身的样式。
这里介绍的一些可在子元素上设置的属性包括:
grid-row-start
、grid-column-start 、 grid-row-end
、grid-column-end
属性grid-column
、grid-row
属性grid-area
属性
先来说一下他们的关系:
-
grid-row-start
/grid-column-start / grid-row-end
/grid-column-end
四个基本属性,对应控制子元素的:起始行网格线
/起始列网格线
/终止行网格线
/终止列网格线
。grid-column
、grid-row
以及grid-area
属性则对这些基本属性进行了简写 -
grid-column
是grid-column-start / grid-column-end
的简写,grid-row
是grid-row-start
/grid-row-end
的简写 -
grid-area
是grid-row-start
/grid-column-start / grid-row-end
/grid-column-end
的简写
设置子元素区域
我们可以使用下面这些属性组合来为当前子元素设置占据的网格区域:
grid-row-start
+grid-column-start
+grid-row-end
+grid-column-end
grid-row
+grid-column
grid-area
其实这都是同一种方式,仅仅是缩写或是全写组合的区别。我们先从最简单的第一种方式看起。
以下我们将所有子元素的混合模式均设置为“强光”,通过改变的“子元素1”的位置,来理解这些属性的用法。
grid-row-start
+ grid-column-start
+ grid-row-end
+ grid-column-end
如上文所言 —— 子元素有关Grid布局的其它属性(grid-row
、 grid-column
、grid-area
)的值由这四个基本属性组合而成。
这四个基本属性可以接受这些值:
- 整数,表示网格线的索引,起始值为1。若给定的整数是一个负数,那么网格线的索引将会从最后一个算起(即倒数),此时起始值为**-1**。子元素将会从给定的网格线索引处开始 / 结束。形如:
grid-row-start: 1;
grid-column-start: 2;
grid-row-end: 3;
grid-column-end: 4;
表示该子元素的行从网格中第1根网格线开始,到第3根网格线结束;列则从第2根网格线开始,到第4根网格线结束。
- 父元素
grid-template-areas
属性中设定的网格区域名称。子元素起始 / 终止网格线默认根据给定网格区域来确定,根据属性名是start
还是end
来确定是使用区域的起始网格线还是终止网格线(一般来说会覆盖给定的网格区域);可选在网格区域名称后方加-start
或-end
后缀强制规定是使用该区域的起始网格线还是终止网格线。形如:
grid-row-start: cell1;
grid-column-start: cell4;
grid-row-end: cell8-start;
grid-column-end: cell8-end;
表示该子元素的行从cell1区域的起始网格线开始,到cell8区域的起始网格线结束;列则从cell4区域的起始网格线开始,到cell8的终止网格线结束。
表示该子元素从cell1区域的行起始网格线、cell4区域列起始网格线开始,到cell8区域行起始网格线、cell8区域列终止网格线结束。(糟糕的措辞,建议看图理解。。。😵)
span
关键字 + 正整数,表示从某个网格线开始算起,再延伸多少网格线(类似于表格中的合并单元格)。必须在同一维度的属性上成对使用形如这样的值,且该对属性中另一个值必须为表示网格线索引的整数或区域名称,使子元素占据的区域有具体的起始 / 终止网格线。形如:
grid-row-start: cell1;
grid-column-start: span 1;
grid-row-end: span 3;
grid-column-end: cell8-end;
表示该子元素的行从cell1区域的起始网格线开始,延伸3个网格线结束;列则从cell8的终止网格线开始,延伸1个网格线结束。
注意:此处span
后的整数必须是正整数,表示延伸了几根网格线。例如此处设为span -3
,表示延伸 -3 个网格线 —— 这显然不符合常理。
grid-row
+ grid-column
grid-row
表示子元素起始行网格线(grid-row-start
)、终止行网格线(grid-row-end
),grid-column
表示子元素起始列网格线(grid-column-start
)、终止列网格线(grid-column-end
)。
它们和上文所述的四个基本属性的语法一致,但可接受两个值,两个值之间使用 /
分隔。前一个值表示起始网格线,后一个值表示终止网格线。形如:
grid-row: cell1 / 3;
grid-column: cell5 / span 2
当然该属性也可以只接受一个值:
- 如果该值是网格区域名称,则子元素的起始、终止网格线即对应该区域的起始、终止网格线。相当于如下设置:
// 缩写
grid-row: cell1;
// 全写
grid-row-start: cell1;
grid-row-end: cell1;
- 如果该值是网格线索引,则子元素起始网格线为该值,终止网格线为
auto
。相当于如下设置:
// 缩写
grid-row: 1;
// 全写
grid-row-start: 1;
grid-row-end: auto;
grid-area
表示的是子元素在网格中所在区域。
该属性接受的值形式十分多样😵
下文提到了 “四个值中不足部分的对应值” ,可能此处略有晦涩 —— 这里的对应是行属性和列属性的对应,即
grid-row-start
对应grid-row-end
,grid-column-start
对应grid-column-end
。
-
如果设置了四个值 ——
- 即上文提及的的四个基本属性。四个基本属性在该属性中以
/
分隔进行设置,顺序是:grid-row-start
/grid-column-start
/grid-row-end
/grid-column-end
。
- 即上文提及的的四个基本属性。四个基本属性在该属性中以
-
如果设置了三个值 ——
- 若第二个值为数值,则第四个值自动设为
auto
; - 若第二个值为区域名称,则第四个值自动设为该网格名称。
- 若第二个值为数值,则第四个值自动设为
-
如果设置了两个值 ——
- 若某个值为数值,则四个值中不足部分的对应值设为
auto
; - 若某个值为区域名称,则四个值中不足部分对应值设为该区域名称;
- 若某个值为数值,则四个值中不足部分的对应值设为
-
如果设置了一个值 ——
- 若这个值为数值,则四个值中不足部分的对应值设为
auto
; - 若这个值为区域名称 —— 则子元素所在位置便是区域名称所指定的位置,相当于将四个值全设为该区域名称。参考下方:
grid-area
:标识子元素?
- 若这个值为数值,则四个值中不足部分的对应值设为
grid-area
:标识子元素?
回到整篇文章中最开始介绍的简易Demo。在此前笔者认为 grid-area
的作用是用于标识子元素的。
经过上文的了解,笔者发现之前所理解的所谓“标识子元素”的说法是不准确的,此处仅仅是因为子元素grid-area
设置的网格区域只有一个值,且恰好和grid-template-areas
定义的网格一致,这就误打误撞刚好实现了我们想要的效果。👀
上文我们根据子元素的 grid-area
属性,在网格容器上使用grid-template-areas
对子元素进行排布。我们为每个子元素的 grid-area
设置了不同的值,来标识子元素,从而在grid-template-areas
属性中以直观的方式进行了布局。
<style>
.grid-wrap {
height: 100%;
display: grid;
grid-template: 25% 25% 50% / 50% 50%;
grid-template-areas:
'cell1 cell3'
'cell1 cell4'
'cell2 cell5';
}
.grid-cell {
background-color: #333;
color:#fff
}
</style>
<div class="grid-wrap">
<section class="grid-cell" style="grid-area:cell1">1</section>
<section class="grid-cell" style="grid-area:cell2">2</section>
<section class="grid-cell" style="grid-area:cell3">3</section>
<section class="grid-cell" style="grid-area:cell4">4</section>
<section class="grid-cell" style="grid-area:cell5">5</section>
</div>
以第一个.grid-cell
元素为例:
/* 这里我们让该子元素出现在cell1的位置 */
grid-area: cell1;
/* 相当于 */
grid-area: cell1 / cell1 / cell1 / cell1;
/* 相当于 */
grid-row-start: cell1;
grid-column-start: cell1;
grid-row-end: cell1;
grid-column-end: cell1;
子元素相互覆盖问题
值的注意的是,如果我们按照“标识子元素”的理解来在网格容器中放置子元素,可以发现子元素是完全按照容器grid-template-areas
规定的矩形网格区域来严格放置的,因此不会造成子元素之间的相互重叠。
但是如果按照前文所说,以设置子元素起始网格线与终止网格线来放置元素的话,子元素将可能发生重叠,正如我们在前文中的一些截图上看到的 “子元素1” 被其它子元素覆盖了 —— 这里遵循“后来居上”的原则,“子元素1”的节点在其它节点之前,因此被覆盖。类似:
要解决这个问题,其实也比较简单 —— 直接为“子元素1”设置 z-index
属性即可,确保它在其它子元素之上。如图:
经过测试,似乎为“子元素1”设置任意大小的transform: translateZ();
值也能达到这个效果。
(2021年3月6日补充)当然,这种覆盖也为我们要实现元素覆盖的效果提供了一种新思路。早前实现这种效果我们可以使定位,但现在有了Grid布局自然就更灵活了一些。参见张鑫旭大佬近期发布的文章:使用grid-area等Grid布局属性轻松实现元素层叠效果
自动放置的子元素设置网格线后自动换行的问题
如果为自动放置的元素设置grid-column
,若同一行元素网格线发生重叠,则冲突元素以及后方元素将会换行。如图:
这样就会造成一部分网格单元没有被完全利用,网格容器中出现空隙。若要利用所有网格单元,可以在网格容器grid-auto-flow
上添加dense
值。如图: