The stacking context

层叠上下文

层叠上下文是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 元素层级的一个层级,因为只有某些元素才会创建层叠上下文。可以这样说,没有创建自己的层叠上下文的元素 将被父层叠上下文包含。

示例

Example of stacking rules modified using z-index

在这个例子中,每个被定位的元素都创建了独自的层叠上下文,因为他们被指定了定位属性和 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 为 2
      • DIV #3 - z-index 为 4
        • DIV #5 - z-index 为 1,在一个 z-index 为 4 的元素内层叠,所以渲染次序为 4.1
        • DIV #6 - z-index 为 3,在一个 z-index 为 4 的元素内层叠,所以渲染次序为 4.3
        • DIV #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

参考

Original Document Information

文档标签和贡献者