理解z-index
与堆叠上下文 stacking context
。
堆叠上下文
stacking context
称为堆叠上下文
。在css中,有很多上下文的概念,那么什么是上下文呢?上下文就是一个布局环境的意思,在同一个环境内,各个元素的布局方式,要遵循这个环境里面定义的各种规则。比如BFC
,只要在同一个BFC
里面,在达到条件的时候就可以触发特定的布局行为,比如浮动、比如外边距合并,当不在同一个BFC
的时候,这些特定的布局行为就不生效了。
堆叠上下文
跟BFC
一样,也是一个布局环境,它用来解决什么问题呢?它解决的是当处于不同的布局上下文(BFC
IFC
flex
table
等)中的box
与其它box
发生重叠的时候,它们之间的重叠先后顺序问题,就是“谁覆盖谁”的问题。 所以堆叠上下文
是针对所有的box
而言的,不管这些box
的布局上下文是不是相同类型,是不是同一个,只要box
发生重叠,它们就要满足堆叠上下文
的规则进行展示。
堆叠上下文
可以包含子堆叠上下文
,就像BFC
可以包含BFC
一样。
在css2.1里面,每个box
在渲染时的位置由3个值构成:x, y, z。 x和y分别是指水平和垂直方向的位置,它们是根据前面已经学过的box model
float
normal-flow
position
等相关布局内容计算出来的,描述box
在网页这个平面中的布局坐标。除了x,y之外,box
的布局位置还有一个z值,描述了box
在用户的眼睛与网页平面的那条垂直线上的布局层次,box
的z值越大,代表它的层级越高,离用户的眼睛就越近,层级高的box
总是渲染在层级低的box
的前面,当它们发生重叠时,层级高的就会覆盖在层级低的上面。那条垂直线,就是css
布局里面的z轴,stacking context
描述的就是box
在z轴上的布局先后关系。
z
值所对应的布局层级,就是box
在z轴上的stack level
。默认情况下,所有box
的stack level
都是0,在同一个stacking context
当中,如果box
的stack level
相同,则box
会按照它们在document tree
中的先后关系堆叠渲染,也就是说发生重叠时,后创建的box
会覆盖在先创建的box
之上。比如:1
2
3
4<div style="width: 500px; margin: 10px auto">
<div style="height: 100px; background-color: cadetblue;"></div>
<div style="margin: -20px 0 0 20px; height: 100px; background-color:cornflowerblue"></div>
</div>
这个效果中,两个带背景色的div的stack level
都是0,且位于同一个stacking context
当中,但是第二个div因为负的margin导致它与前一个div发生重叠,最后按照元素的先后关系,第二个div覆盖在了第一个div之上。
一开始网页只有一个stacking context
,由root element
创建。
每个box
只属于一个stacking context
。
z-index
property
z-index
这个属性有两个作用,一是指定box
在它所在的堆叠上下文中的层级stack level
,二是可以给box
创建新的堆叠上下文,布局子内容。它的定义如下:
Value:
auto | <integer> | inherit
初始值: auto
应用于: positioned elements,是指position
为relative | absolute | fixed
的元素
是否可继承: no
百分比: 不支持
各个值的含义如下:
<interger>
整型值用来指定box
在当前堆叠上下文中的stack level
,可以为任意整数,包括负数;同时它还会创建一个新的堆叠上下文;auto
指定box
在当前堆叠上下文中的stack level
为0
,但是不会创建新的堆叠上下文
注意:z-index:0
与z-index:auto
的区别,两者都代表stack-level
是0,但是z-index:0
会创建新的堆叠上下文,而z-index:auto
不会。
painting order
结合stack level
以及box tree
本身布局的特性,每个堆叠上下文
都遵循以下这个顺序(painting order
)在z
轴上渲染相关的内容。这个顺序依次是从下到上,越靠后的内容它在堆叠上下文
中的层级越高:
- 先渲染形成
堆叠上下文
的box
的background
和border
- 渲染
stack level
为负
的child
stacking contexts
,stack level
越小的在越底下 - 渲染未定位的、文档流中的
block box
- 渲染未定位的
float box
,注意float box
可以结合position: relative
变为定位的 - 渲染未定位的、文档流中的
inline box
,包括普通的inline content
以及inline tables
和inline blocks
- 渲染
stack level
为0
的child
stacking contexts
,以及设置了定位的但stack level
也为0
的后代元素
- 渲染
stack level
大于0
的child
stacking contexts
,stack level
越大的在越上面
注重说明:
- 上面顺序中的每一项,都可以看作是一个层,越后面的层,在z轴的位置,肯定比前面的层高;在同一个层中,不同的内容首先根据
stack level
来决定堆叠顺序,stack level
相同时,则根据它们在document tree
中的先后顺序,决定堆叠顺序; 未定位
的意思是值position
为static
,因为其它position
值,当设置了非auto
的z-index
后,会创建stacking context
stack level
为0
的child stacking context
是指,设置了非static
的position
,且z-index:0
的box
所新建的stacking context
stack level
为0
的定位元素
是指,设置了非static
的position
,且z-index:auto
的box
- 上面说的是在一个
stacking context
中的堆叠渲染顺序,第2 6 7
都涉及都有child stacking context
,如果有,则每个child stacking context
也都按照上面的顺序来堆叠展示自己内部的内容,所以stacking context
的堆叠渲染,是一个类似递归的渲染处理方式。某个child stacking context
内部,如果一个box的stack level
设置的特别大,超过网页里所有其它内容的stack level
,它最终也不一定会渲染在页面内容的最顶部,因为它是在一个child stacking context
里面渲染的,只要这个child stacking context
本身的stack level
低于其它内容,它自己包括它的子内容就始终会在其它内容下面渲染。
这是css关于以上层叠渲染顺序的算法逻辑:堆叠上下文的详细算法逻辑,也是浏览器帮我们实现的。
通过下面这个例子来理解上面的层叠渲染顺序:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
.layer1 {
position: relative;
z-index: 0;
width: 500px;
padding: 10px;
border: 1px solid #ccc;
background-color: #e2e2e2;
}
.layer2 {
position: absolute;
width: 100px;
height: 100px;
z-index: -1;
background-color: darkgoldenrod;
}
.layer3 {
margin: 1em;
padding: 10px;
border: 5px solid #ccc;
}
.layer4 {
width: 100px;
height: 200px;
float: left;
background-color: skyblue;
margin: 10px;
}
.layer5 {
margin-left: -57px;
background: red;
color: #fff;
display: inline-block;
}
.layer6 {
position: absolute;
width: 100px;
height: 100px;
background-color: cadetblue;
top: 190px;
}
.layer7 {
position: absolute;
width: 100px;
height: 100px;
background-color: blueviolet;
top: 231px;
left: 45px;
}
</style>
</head>
<body>
<div class="layer1">
<div class="layer2"></div>
<div class="layer3">Lorem ipsum dolor sit amet consectetur adipisicing elit. Qui vero quae nostrum debitis
<span class="layer4"></span>necessitatibus commodi, soluta ea amet perferendis magni voluptate provident nam.
Dicta ducimus
rerum aspernatur id eaque assumenda.</div>
<div class="layer3">
<div class="layer5">Lorem ipsum dolor</div> sit amet consectetur adipisicing elit. Qui vero quae nostrum debitis
necessitatibus commodi, soluta ea amet perferendis magni voluptate provident nam. Dicta ducimus rerum
aspernatur id eaque assumenda.
</div>
<div class="layer6"></div>
<div class="layer7"></div>
</div>
</body>
</html>
这个例子中的css
类全部都用层叠顺序中对应的顺序名,方便理解它们的层叠关系。
后记
上面的内容属于css2.1中的规范,到目前来说仍然属于比较靠谱的知识点,但是css发展地很快,后面新增的内容可能会调整这个堆叠上下文
的知识点,所以上面的知识,在当前来说是不完整的。 不过以上内容,对于处理网页开发中涉及层叠渲染顺序的问题,已经够用了。