层叠上下文是HTML
元素的三维概念,这些HTML
元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的z
轴上延伸,HTML
元素依据其自身属性按照优先级顺序占用层叠上下文的空间。
层叠上下文
在之前的增加 z-index
的例子中, 某些 DIV
的渲染顺序是由 z-index
的值影响的。这是因为这些 DIV
具有 使他们形成一个层叠上下文的特殊属性。
文档中的层叠上下文由满足以下任意一个条件的元素形成:
- 根元素 (HTML),
z-index
值不为 "auto
"的 绝对/相对定位,- 一个
z-index
值不为 "auto
"的flex
项目 (flex item
),即:父元素display:flex|inline-flex
, opacity
属性值小于1
的元素(参考the specification for opacity
),transform
属性值不为 "none
"的元素,mix-blend-mode
属性值不为 "normal
"的元素,filter
值不为“none
”的元素,perspective
值不为“none
”的元素,isolation
属性被设置为 "isolate
"的元素,position: fixed
- 在
will-change
中指定了任意CSS
属性,即便你没有直接指定这些属性的值(参考 这篇文章) - -
webkit-overflow-scrolling
属性被设置 "touch
"的元素
在层叠上下文中,其子元素同样也按照上面解释的规则进行层叠。 特别值得一提的是,其子元素的 z-index
值只在父级层叠上下文中有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。
总结:
- 给一个
HTML
元素定位和z-index
赋值创建一个层叠上下文,(opacity
值不为1
的也是相同)。 - 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个有层级的层叠上下文。
- 每个层叠上下文完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
- 每个层叠上下文是自包含的:当元素的内容发生层叠后,整个该元素将会 在父层叠上下文中 按顺序进行层叠。
Note: 层叠上下文的层级是 HTML 元素层级的一个层级,因为只有某些元素才会创建层叠上下文。可以这样说,没有创建自己的层叠上下文的元素将被父层叠上下文包含。
示例节
在这个例子中,每个被定位的元素都创建了独自的层叠上下文,因为他们被指定了定位属性和 z-index
属性。层叠上下文的层级如下:
- Root
- DIV #1
- DIV #2
- DIV #3
- DIV #4
- DIV #5
- DIV #6
注意 DIV#4,DIV #5
和 DIV #6
是 DIV #3
的子元素,所以它们的层叠完全在 DIV #3
中被处理。一旦 DIV #3
中的层叠和渲染处理完成,DIV #3
元素作为一个整体传递给 root
元素,并相对兄弟元素层叠。
注意:
DIV #4
被渲染在DIV #1
之下,因为DIV #1
的z-index (5)
在root
元素的层叠上下文中生效,而DIV #4
的z-index (6)
在DIV #3
的层叠上下文中生效。因此,DIV #4
在DIV #1
之下,因为DIV #4
归属于z-index
值较低的DIV #3
元素。- 由此可得
DIV #2
(z-index 2) 被渲染在DIV #5
(z-index 1) 之下,因为DIV #5
归属于z-index
较高的DIV #3
元素。 DIV #3
的z-index
值是 4,但是这个值独立于DIV #4,DIV #5
和DIV #6
的z-index
值,因为他们从属于不同的层叠上下文。- 分辨出层叠的元素在
Z
轴上的渲染顺序的一个简单方法是将它们想象成一系列的版本号,子元素是其父元素版本号之下的次要版本。通过这个方法我们可以轻松得看出为什么一个z-index
为 1 的元素(DIV #5
)层叠于一个z-index
为2
的元素(DIV #2
)之上,而一个z-index
为6
的元素(DIV #4
)层叠于z-index
为5
的元素(DIV #1
)之下。在我们的例子中(依照最终渲染次序排列): Root
DIV #2
-z-index
为 2DIV #3
-z-index
为 4DIV #5
-z-index
为 1,在一个z-index
为 4的元素内层叠,所以渲染次序为 4.1DIV #6
-z-index
为 3,在一个z-index
为 4的元素内层叠,所以渲染次序为 4.3DIV #4
-z-index
为 6,在一个z-index
为 4的元素内层叠,所以渲染次序为 4.6
DIV #1
-z-index
为 5
示例
HTML
<div id="div1">
<h1>Division Element #1</h1>
<code>position: relative;<br/>
z-index: 5;
</div>
<div id="div2">
<h1>Division Element #2</h1>
<code>position: relative;<br/>
z-index: 2;
</div>
<div id="div3">
<div id="div4">
<h1>Division Element #4</h1>
<code>position: relative;<br/>
z-index: 6;
</div>
<h1>Division Element #3</h1>
<code>position: absolute;<br/>
z-index: 4;
<div id="div5">
<h1>Division Element #5</h1>
<code>position: relative;<br/>
z-index: 1;
</div>
<div id="div6">
<h1>Division Element #6</h1>
<code>position: absolute;<br/>
z-index: 3;
</div>
</div>
CSS
* {
margin: 0;
}
html {
padding: 20px;
font: 12px/20px Arial, sans-serif;
}
div {
opacity: 0.7;
position: relative;
}
h1 {
font: inherit;
font-weight: bold;
}
#div1,
#div2 {
border: 1px dashed #696;
padding: 10px;
background-color: #cfc;
}
#div1 {
z-index: 5;
margin-bottom: 190px;
}
#div2 {
z-index: 2;
}
#div3 {
z-index: 4;
opacity: 1;
position: absolute;
top: 40px;
left: 180px;
width: 330px;
border: 1px dashed #900;
background-color: #fdd;
padding: 40px 20px 20px;
}
#div4,
#div5 {
border: 1px dashed #996;
background-color: #ffc;
}
#div4 {
z-index: 6;
margin-bottom: 15px;
padding: 25px 10px 5px;
}
#div5 {
z-index: 1;
margin-top: 15px;
padding: 5px 10px;
}
#div6 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
width: 150px;
height: 125px;
border: 1px dashed #009;
padding-top: 125px;
background-color: #ddf;
text-align: center;
}
Result