布局与定位 #
浮动布局 #
浮动布局的好处:
- 可以让元素向左或者向右靠拢
- 可以解决一些边距问题
- 可以实现文字包围图片的样式
float: left/right;
会让元素脱离文档流。
元素之间的多个空白,会合并成一个空格。如果不处理会出现一些莫名其妙的间距。用浮动就可以解决这个问题。元素脱离了文档流,空白也就默认被忽略了。 并且会紧紧靠近父元素的边缘,或者同样是浮动元素的边缘。
例如下面的 html,三个 <div class="child"></div>
之间都有换行和空格,html 会将多个空白空格合并为一个空格。就会造成页面的元素之间看起来有间距,
其实就是一个空格。
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
如果不想有空格,可以像下面这样,把换行和空格去掉:
<div class="parent">
<div class="child"></div><div class="child"></div><div class="child"></div>
</div>
上面的方式,不好看,可以使用浮动解决:
.child {
float: left
}
第一个子元素 <div class="child"></div>
就会去找父元素的左边边缘,第二个第三个也一样,但是第二个第三个由于中间有浮动元素,就会选择靠近浮动元素的边缘。
清除浮动 #
浮动会导致父元素的高度塌陷。
比如 div
块容器会占一整行,如果该元素里面包含有浮动元素,会导致该元素的高度没有了。
因为浮动元素脱离了文档流,父元素会认为没有子元素,高度也就没有了。
解决方式:
- 设置父元素的高度(前提是父元素的高度是已知的)。
- 父元素的高度未知的情况下,可以通过清除浮动的方式,原理就是让父元素重新计算元素的高度。
- 在父元素最后添加一个子元素
div
,并给子元素添加属性clear: both;
,缺点是会多一个空的div
。
- 在父元素最后添加一个子元素
- 终极方案:原理与上个方法一样,通过伪元素来清除浮动。
伪元素来清除浮动:
.parent {
}
.parent:after{
content: "";
display: block;
clear: both;
}
上面的示例中给父元素的类 parant
添加了一个 :after
伪元素。
弹性布局 #
弹性布局可以更方便的布局,但是对浏览器要求较高。
概念:
- 弹性容器:设置了
display: flex;
的元素即为弹性容器。 - 弹性子元素(项目):弹性容器里的直接子元素。
display: flex
:如果一个元素的设置了这个属性(弹性容器),那么他的直接子元素(孙子元素就不是弹性布局),就会按着弹性布局的方式来布局。
<head>
<style>
.parent {
display: flex;
width: 600px;
height: 600px;
}
.child {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</body>
如果 parent
不是弹性布局,那么三个 child
都是块元素,每个元素会占据一整行。但是 parent
添加了 display: flex;
属性以后,三个子元素会在一行并排显示,不会有间距。
直接子元素是弹性布局,但是
parent
元素本身还是块级布局。
弹性主轴和侧轴 #
弹性布局有一个主轴和一个侧轴:
- 主轴:默认是水平向右,可以修改为水平向左或竖直向上,竖直向下。
- 侧轴(交叉轴):默认是竖直向下,可以修改为竖直向上或水平向左,水平向右,
弹性布局的子元素默认是在主轴上一行或者一竖,不会换行,默认情况下(flex-wrap: nowrap
)如果一行子元素的宽度或者高度超过了父元素,所有的子元素就会等比例缩小。
设置主轴的方向:
flex-derection: row
:默认是row
。row
:水平向右。row-reverse
:水平向左。column
:竖直向下。column-reverse
:竖直向上。
设置主轴的排布:
justify-content: flex-start
:默认是flex-start
。flex-start
:靠近主轴的起点。flex-end
:靠近主轴的终点。center
:主轴居中。space-between
:平均分布,和主轴的起点和终点没有间距。space-around
:平均分布,和主轴的起点和终点有间距,两边的间距是中间的一半。space-evenly
:平均分布,间距一致。
弹性布局,设置水平居中只需要 justify-content:center
就可以实现,如果不是弹性布局,可以用下面的方式:
display: block; /* 设置为块级元素 */
margin: 0 auto; /* auto 设置水平居中,必须是块元素 */
设置侧轴的排布:
align-items: stretch
:默认是stretch
。stretch
:拉伸,如果子元素没有设置高度或宽度,那么子元素会被拉伸到和父元素一样的高度或宽度。flex-start
:靠近侧轴的起点。flex-end
:靠近侧轴的终点。center
:侧轴居中。单行的侧轴没有平均分布。
换行:
flex-wrap: nowrap
:默认是nowrap
。nowrap
:不换行。wrap
:换行,如果侧轴排布是stretch
,换行以后是两行,那么两行会被拉伸,各占一半。
多行存在的时候,侧轴分布:
align-content: flex-start
:flex-start
:多行都向侧轴的起点靠拢。flex-end
:多行都向侧轴的终点靠拢。center
:多行居中。space-around
:平均分布,和侧轴的起点和终点有间距,两边的间距是中间的一半。space-between
:平均分布,和侧轴的起点和终点没有间距。space-evenly
:平均分布,间距一致。
弹性子元素会存在多个,如果要单独设置一个子元素侧轴的分布,可以给弹性子元素添加属性:
align-self: flex-start
:flex-start
:靠近侧轴的起点。flex-end
:靠近侧轴的终点。center
:侧轴居中。
主轴是不能单独设置一个子元素的分布的。
弹性子元素的排序 #
如果要设置弹性子元素的排序,可以给每个子元素添加属性:
order: {num}
子元素会沿主轴方向从小到大排序。
示例:
<head>
<style>
.parent {
display: flex;
width: 600px;
height: 600px;
}
.child {
width: 200px;
height: 200px;
}
.c1 {
order: 3;
background: skyblue;
}
.c2 {
order: 2;
background: green;
}
.c3 {
order: 1;
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="child c1"></div>
<div class="child c2"></div>
<div class="child c3"></div>
</div>
</body>
弹性子元素剩余空间配置 #
给子元素添加属性 flex: {num}
,占据剩余份额的份数。flex: 1
就表示占据剩余空间的 1 份。
示例:
<head>
<style>
.parent {
display: flex;
width: 600px;
height: 600px;
background: gray;
}
.child {
width: 100px;
height: 100px;
}
/* 剩余空间被分为 3 份,c1 占 1/3,c2 占 2/3 */
.c1 {
flex: 1;
background: skyblue;
}
.c2 {
flex: 2;
background: green;
}
.c3 {
order: 1;
background: yellow;
}
</style>
</head>
<body>
<div class="parent">
<div class="child c1"></div>
<div class="child c2"></div>
<div class="child c3"></div>
</div>
</body>
上面的示例,每个子元素的宽度为 100px
,那么剩余空间就是 300px
。c1
会占据剩余空间的 100px
,c2
占 200px
。
flex-grow、flex-shrink、flex-basis #
flex
是一个复合属性(flex: {flex-grow} {flex-shrink} {flex-basiss}
),它有三个属性:flex-grow
、flex-shrink
、flex-basis
,分别是用来设置弹性子元素的拉伸、收缩和基准值。
flex-grow
:默认值 0。和flex: {num}
的作用是一样的。flex-shrink
:默认值 1。和flex: {num}
的作用是相反的,当子元素的大小超过了主轴或者侧轴,那么设置了flex-shrink
的子元素就会自动收缩。如果设置了换行,那么这个属性就没有用了。flex-basis
:默认值auto
。设置主轴方向的元素的尺寸。如果主轴是横向的,那设置的就是宽度,如果是纵向的,那设置的就是高度。
inline-flex #
display: inline-flex
和 display: flex
的唯一区别就是会把元素本身变为行内元素,元素内部的子元素仍然是弹性子元素。
网格布局 #
弹性布局是基于轴线的布局,可以看作是一维布局,网格布局将容器划分成行和列,产生单元格,可以看作是二维布局。
概念:
- 网格容器:设置了
display: grid;
的元素即为网格容器。 - 项目:网格容器里的直接子元素。
grid-template-columns
:设置网格容器的列宽和列的数量,例如grid-template-columns: 100px 200px 100px;
表示网格容器有三列,列宽分别是100px
、200px
、100px
。grid-template-rows
:设置网格容器的行高和行的数量,例如grid-template-rows: 100px 200px;
表示网格容器有两行,行高分别是100px
、200px
。
网格布局,是看不到网格线的,开发过程中,可以在浏览器中查看元素,选择 grid
标签,如下图:
划分网格 #
fr、auto、minmax #
fr
、auto
、minmax
是网格布局的三个关键字,用来设置网格容器的列宽和行高。都是具有一定收缩性和扩展性的。
优先级:minmax() > fr > auto
。
fr
和auto
最小值都是 0,过多内部存在子元素,那么最小值就是子元素的宽或者高。
fr #
fr
:单位(fraction),有点类似于弹性布局的 flex-grow
,fr
的作用也是把整个容器内剩余的空间做均分,然后按照 fr
来分配。例如 grid-template-columns: 60px 1fr;
表示网格容器有两列,第一列的宽度是 60px
,第二列的宽度是剩余的宽度。所有列都用 fr
来表示,例如 grid-template-columns: 1fr 1fr;
表示网格容器有两列,宽度各占一半。fr
可以快速的把整个网格空间利用起来,例如实现一个九宫格 grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr;
auto #
auto
是用来设置宽高的默认值,但是在网格容器中,有一些特别的用处。
<head>
<style>
.child3 {
height: 30px;
width: 100px;
background-color: salmon;
}
.grid-container {
height: 600px;
width: 600px;
background-color: black;
display: grid;
grid-template-columns: 60px 60px auto;
grid-template-rows: 100px 200px;
}
</style>
</head>
<body>
<div class="grid-container">
<div>111</div>
<div>222</div>
<div class="child3">333</div>
</div>
</body>
上面的示例,效果如下图:
child3
元素的宽度是 100px
,但是这个元素所在的单元格的宽度是 auto
,auto
忽略了子元素的宽度,占满了剩余空间。但是如果新增一例 1fr
:
.grid-container {
/* ... */
grid-template-columns: 60px 60px auto 1fr;
grid-template-rows: 100px 200px;
}
auto
会自动收缩,正好等于子元素的宽度,如下图:
如果有多个 auto
,例如 grid-template-columns: 60px 60px auto auto;
包含了两列 auto
,这两列会把剩余空间平分,如下图:
但是一旦有了一列 fr
,例如 grid-template-columns: 60px 60px auto auto 1fr;
,所有的 auto
都会自动收缩。
minmax() #
minmax({min}, {max})
:用来设置一个范围,例如 grid-template-columns: minmax(100px, 200px);
表示网格容器的第一列的宽度在 100px
到 200px
之间。
注意 min
值不要设置的比 max
大,例如 minmax(200px, 100px)
或者 minmax(1fr, 100px)
。
minmax()
的优先级是高于 auto
的,它会在最大的范围中去压缩 auto
的空间。
repeat #
repeat({重复次数}, {尺寸})
:用来设置重复的列或者行,例如 grid-template-columns: repeat(3, 100px);
表示网格容器有三列,列宽都是 100px
。
auto-fill #
auto-fill
:会按照尺寸去尽可能的生成最多的列或者行,例如:
.grid-container {
height: 600px;
width: 650px;
background-color: black;
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
grid-template-rows: 100px 200px;
}
上面的示例,repeat(auto-fill, 100px)
根据当前容器的剩余空间 650px
最多就只能生成 6 列。
auto-fit #
auto-fit
:也是按照尺寸去尽可能的生成最多的列或者行,但是和 auto-fill
不同的是,它最终生成的列,如果没有元素,那么它会收缩为 0。
如果 auto-fit
的尺寸设置为 minmax
,例如 grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
,那么会生成的列是会把剩余空间均分的。
但如果 auto-fill
的尺寸设置为 minmax
,例如 grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
,那么会按照 min
也就是 100px
去生成列。
gap #
gap
:设置网格容器的行间距和列间距。
- 统一设置间距,例如
grid-gap: 10px;
表示网格容器的行间距和列间距都是10px
。 - 分别设置行和列的间距,例如
grid-gap: 10px 20px;
表示网格容器的行间距是10px
,列间距是20px
。也可以分开设置,例如row-gap: 10px; column-gap: 20px;
:row-gap
:行间距。column-gap
:列间距。
网格排布 #
网格布局的排列顺序默认是先行后列,例如下面的一个九宫格的示例:
<style>
.grid-container {
height: 300px;
width: 600px;
background-color: black;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
padding: 16px;
font-size: 4rem;
color: white;
}
.child {
padding: 8px;
}
.child1 {
background-color: #0055bb;
}
.child2 {
background-color: #66bbff;
}
.child3 {
background-color: #8440f1;
}
.child4 {
background-color: #b88dff;
}
.child5 {
background-color: #ff6666;
}
.child6 {
background-color: #ffdd66;
}
.child7 {
background-color: green;
}
.child8 {
background-color: greenyellow;
}
.child9 {
background-color: pink;
}
</style>
<div class="grid-container">
<div class="child child1">1</div>
<div class="child child2">2</div>
<div class="child child3">3</div>
<div class="child child4">4</div>
<div class="child child5">5</div>
<div class="child child6">6</div>
<div class="child child7">7</div>
<div class="child child8">8</div>
<div class="child child9">9</div>
</div>
显示效果:
元素先从第一行开始,从左到右排列。
使用 grid-auto-flow: column
设置为先列后行。
grid-auto-flow
属性除了设置成 row
和 column
,还可以设成 row dense
和 column dense
。这两个值主要用于,某些项目指定位置以后,剩下的项目怎么自动放置。
例如 row dense
,表示"先行后列",并且尽可能紧密填满,尽量不出现空格。
网格元素的尺寸 #
网格中的子元素如果没有设置尺寸,那么默认会拉伸到所在网格的大小。
网格中子元素的大小和网格的大小是没有关系的:
- 如果网格的宽或者高是一个可变的值,例如
1fr
,子元素的宽高大于1fr
的时候会把网格撑开。 - 如果网格的宽或者高是一个固定的值,例如
200px
,子元素的宽高大于200px
的时候,子元素会忽略网格的大小。
order #
网格子元素和弹性子元素一样也可以设置 order
属性来排序。网格子元素的 order
属性默认是 0.
按网格线设置元素位置 #
网格边缘上的数字就是网格线的编号。列和行的网格线都是从 1 开始编号。下图中的负数,是反向编号,方便从后开始查找网格线。
每个网格都是由四根网格线包围的,例如上图中的元素 1,它是有行的 1 号、2 号,列的 1 号、2 号网格线包围的。可以通过指定元素上下左右的 4 根网格线来设置元素在网格中的位置。
例如上图,如果要把 7 号元素放到 2 号元素的位置:
.child7 {
background-color: green;
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}
也可以占据多格,例如:
.child7 {
background-color: green;
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
}
grid-column-start: 2;
和grid-column-end: 4;
可以简写成grid-column: 2 / 4;
grid-row-start: 1;
和grid-row-end: 3;
可以简写成grid-row: 1 / 3;
自定义网格线名称 #
网格线虽然后编号,但是不容易记住,可以在定义列和行时自定义网格的名称。
grid-template-columns: [line1 aaa] 100px [line2] 200px [line3] 300px [line4]
,- 第一列
100px
左边的网格线(编号 1)命名line1
和aaa
。 - 第二列
200px
左边的网格线(编号 2)命名为line2
。 - 第三列
300px
左边的网格线(编号 3)命名为line3
,右边的网格线(编号 4)命名为line4
。
- 第一列
grid-template-rows: [line5] 100px [line6] 100px 100px
- 网格线可以定义多个名字,用空格分隔,如
[line1 aaa]
。 - 不需要定义所有的网格线名称,只定义需要用到的即可。如
[line5] 100px [line6] 100px 100px
。 - 定义了名称的网格线,编号仍然是可以使用的。
grid-template-areas #
网格布局是可以预先将网格划分区域的,一个区域由一个或多个单元格组成。grid-template-areas
属性用于定义区域。
.grid-container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas: 'a a b'
'c c b'
'd e f';
}
面代码先划分出一个九宫格,然后定义了每个单元格所属的区域。
如果某些单元格不需要利用,则使用 .
表示:
.grid-container {
grid-template-areas: 'a a b'
'c c b'
'. . .';
}
.child1 {
background-color: #0055bb;
grid-area: a;
}
.child2 {
background-color: #66bbff;
grid-area: b;
}
.child3 {
background-color: #8440f1;
grid-area: c;
}
注意:
- 划分区域的方式的缺点就是每一个单元格都要去设置区域,不用的单元格也要用
.
表示,如果单元格很多,就比较麻烦。 - 网格线划分优先级要高于区域划分。
- 区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start
,终止网格线自动命名为区域名-end
。
隐形网格 #
加入网格容器划分了九个单元格,但是我们在网格容器中放置了超过 10 个或者更多的子元素,这时,浏览器会自动生成多余的网格,以便放置子元素。这种自动生成的网格就叫做隐形网格。
grid-auto-columns
和 grid-auto-rows
属性就是用来设置,浏览器自动创建的多余网格的列宽和行高。如果不指定这两个属性,浏览器根据单元格内容的大小,决定新增网格的列宽和行高。
用法和 grid-template-columns
、grid-template-rows
是一样的。
网格单元中子元素的位置 #
在单元格中的子元素,如果没有设置宽高,那么会自动撑满整个单元格,如果设置了宽高,那么可以使用 justify-items
和 align-items
来设置子元素在单元格中的位置。justify-items
和 align-items
都是容器属性。
justify-items
:水平方向,可选值start
,end
,center
,strech
。默认值是strech
。align-items
:垂直方向,可选值start
,end
,center
,strech
。默认值是strech
。
容器设置了这两个属性后,所有单元格内的元素都会按照这个位置来排布。
如果想要单独设置某个单元格的子元素,可以使用 justify-self
和 align-self
。使用方法和 justify-items
、align-items
一样。
place-self: {align-self} {justify-self}
是 justify-self
和 align-self
的复合属性。
网格在容器中的位置 #
justify-content
、align-content
用来设置整个网格在容器中的排布,分别表示水平方向和垂直方向的排布。当整个网格没有撑满容器时,就可以使用这两个属性,可选值:
start
:网格在起始边缘对齐。end
:网格在结束边缘对齐。center
:网格居中对齐。strech
:网格单元大小保持不变,网格单元的间隔拉伸,填满容器。space-around
:平均分布,每个网格单元的两侧的间隔相等。space-between
:平均分布,网格单元的之间的间隔相等,第一个单元贴近起始边缘,最后一个贴近结束边缘。space-evenly
:平均分布,间距一致。
inline-grid #
display: inline-grid
和 display: grid
的唯一区别就是会把元素本身变为行内元素,元素内部的子元素仍然是网格元素。
定位 #
可以设置元素具体在某个位置上。元素默认就是 static
,也就是没有定位。
relative
、absolute
、fixed
这三个属性值有一个共同点,都是相对于某个基点的定位,只是基点不同。
文档流 #
文档流(Normal Flow)简单说就是 HTML 元素的一种排布规则,元素默认是从上到下、从左到右依次排列(盒模型)。不同的布局模式,例如弹性布局或者网格布局,会有不同的排布规则。 不管是哪种文档流,本质都是对内部元素进行空间分配,元素与元素之间不产生重叠。
脱离文档流 #
脱离文档流是指,元素会被文档流忽略,不分配空间。脱离文档流的元素可以理解为漂浮在文档流的上方。当一个元素脱离文档流后,文档流中的其他元素将忽略该元素并填补其原先的空间。
脱离文档流的方法有浮动 float
,绝对定位 position:absolute
和固定定位 position:fixed
。
static #
static
表示浏览器会按照源码的顺序,决定每个元素的位置,每个块级元素占据自己的区块,元素与元素之间不产生重叠,这个位置就是元素的默认位置。
static
定位的元素位置,是浏览器自主决定的,所以这时 left/right/top/bottom
这四个属性是无效的。
相对定位 #
position: relative
:相对于默认位置(即 static
时的位置)进行偏移,虽然元素根据 left/right/top/bottom
这四个属性进行了偏移,但是在文档流中占据的位置是不变的。
div {
position: relative;
top: 20px;
}
上面的示例,div
元素从默认位置向下偏移 20px
(即距离顶部 20px
)。
绝对定位 #
position: absolute
:相对于最接进自身并且设置了非 static
定位的父元素或者祖先元素(不是 static
的元素)。配合 left/right/top/bottom
属性使用。
设置了绝对定位的元素,会脱离文档流,不会占据空间。正常的元素会顶上去。
设置了绝对定位的元素的位置如何确定?
- 没有设置定位偏移属性(
left/right/top/bottom
)的情况
要根据父元素的文档流模式来确定位置,例如 flex
布局:
弹性容器设置了 justify-content: start;
:
弹性容器设置了 justify-content: end;
:
弹性容器设置了 justify-content: center;
:
- 设置了定位偏移属性的情况
元素的定位基点是设置了非 static
定位的最近的父元素或者祖先元素,如果没有非 static
定位的祖先元素,那么会以浏览器显示区域边界来进行定位。
元素设置 position: absolute;bottom: 20px;left: 20px;
:
固定定位 #
position: fixed
:固定在浏览器窗口中的某个位置,相对于浏览器窗口定位。配合 left/right/top/bottom
属性使用。
设置了固定定位的元素,会脱离文档流,不会占据空间。
设置了固定定位的元素的位置如何确定?
- 没有设置定位偏移属性(
top
、bottom
、left
、right
)的情况下,和绝对定位的表现是一样的。 - 设置了定位偏移属性的情况下,元素的定位基点是浏览器的显示区域边界。无论页面如何滚动,元素的位置是固定不变的。
粘性定位 #
sticky
的定位基点是设置了 overflow:scroll
的最近的祖先元素。如果没有就以浏览器显示区域边界来进行定位。
sticky
定位不会脱离文档流。
sticky
会产生动态效果,很像 relative
和 fixed
的结合。比如,网页的搜索工具栏,初始加载时,在自己的默认位置(relative
定位),页面向下滚动时,工具栏可以在距离浏览器相对应的位置固定住,始终停留在页面头部(fixed
定位)。等到页面重新向上滚动回到原位,工具栏也会回到默认位置。必须配合 left/right/top/bottom
属性使用。
当页面滚动,父元素开始脱离视口时(即部分不可见),只要与 sticky
元素的距离达到生效门槛,relative
定位自动切换为 fixed
定位;等到父元素完全脱离视口时(即完全不可见),fixed
定位自动切换回 relative
定位。sticky
元素这个时候也是不可见的。
层 #
堆叠上下文 #
堆叠上下文就是一个独立的渲染层,里面的元素会按照自己的堆叠顺序进行渲染。
页面的 <html>
元素是一个默认就有堆叠上下文的,所以被叫做根堆叠上下文。在根堆叠上下文中,元素是可以产生自己的堆叠上下文的。
如何让一个元素产生堆叠上下文:
- 默认情况下,元素的
position
不是static
,z-index
不是auto
,那么该元素就会产生堆叠上下文。 - 弹性(Flex)元素或者网格(Grid)元素,只要设置了
z-index
不是auto
,那么该元素就会产生堆叠上下文。
堆叠顺序 #
- 同一个堆叠上下文中,
z-index
越大,元素的堆叠顺序越靠上。 - 同一个堆叠上下文中,
z-index
相同,那么元素的堆叠顺序就按照元素在 DOM 中的先后顺序。
设置 z-index
只在元素所在的堆叠上下文中有效。一个堆叠上下文中子元素,无论设置的 z-index
是多少,都不会影响其他堆叠上下文的堆叠顺序。如下图:
元素 A
产生了堆叠上下文,并且 z-index
为 1,元素 B
是 A
的子元素,z-index
为 20。但是元素 B
的是无法覆盖的元素 C
的。
也就是说,任意元素的堆叠顺序是会被自己的祖先元素的堆叠上下文限制的,只有那些不存在祖先元素有堆叠上下文的元素,才能参与到根堆叠上下文的堆叠顺序中。所以碰到 z-index
层级高却无法覆盖层级低的元素,就要先去检查一下祖先元素是否有堆叠上下文,然后再设置 z-index
。
上图中,非 static
元素是介于 0 和 1 之间的,只要元素设置了 position
并且不是 static
,那么元素就会跳到红色层级。