stacking context 层叠上下文

层叠上下文

什么是层叠上下文?

在CSS中,每个盒子的位置其实都是三维的。除了平面的X轴和Y轴之外,盒子还会沿着“Z轴”(垂直屏幕靠近用户方向)一个一个地往上堆叠,亦即产生了视觉上的重叠效果。看一下标准文档中给出的示意图:

层叠上下文示意图

这有个不太正确的类比,但也许能帮助你理解它们:层叠上下文就像JS中的执行上下文,内部维护了一些函数(元素盒子),不同函数在调用过程中形成了一个调用栈。元素盒子则是在定义时根据不同的定义方式获得了各自的层叠等级,它们按照层叠等级的高低也形成了一个栈,栈顶离用户最近。

层叠上下文分两种,一种是根元素<body>自动创建的根层叠上下文(root stacking context),另一种是其他元素创建的本地层叠上下文( local stacking contexts)。每个盒子都必属于某个层叠上下文,但不是每个盒子都能创建层叠上下文。下面将整理创建层叠上下文的各种方式。

如何创建层叠上下文?

当一个元素创建了层叠上下文,此时它和两个上下文有关:一个是它所处的当前层叠上下文,另一个是新层叠上下文。新层叠上下文属于当前层叠上下文的一部分。

创建层叠上下文的方法有:

  1. 前面提到的根元素<body>自动创建根层叠上下文
  2. z-index:autoz-index:0定位元素

    For those with ‘z-index: auto’, treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.

对于z-index:auto的定位元素,它的定位后代,以及能够创建层叠上下文的后代,都属于当前上下文。所以可认为 z-index:auto元素并没有创建层叠上下文,而不是像文档所说的”treat the element as if it created a new stacking context”。

For those with ‘z-index: 0’ treat the stacking context generated atomically.

z-index:0 的定位元素自动创建层叠上下文。它的后代元素属于新创建的层叠上下,与z-index:0定位元素所在的层叠上下文中的其他元素无关。

  1. 元素的opactity属性值不为1
  2. 元素的transform属性值不为none
  3. 元素的filter属性值不为1
  4. 当父元素是display:flex|inline-flex,后代元素的z-index不为auto

层叠等级

什么是层叠等级?

层叠上下文中可以包含多个元素盒子。每个盒子都有一个层叠等级(等级可以为负),层叠等级按大小排列形成了第三个轴——“Z轴”,垂直屏幕向用户延申增大。

需要注意的时层叠等级仅在当前层叠上下文中才有排序意义。创建当前层叠上下文的元素,相对再上一层的层叠上下文而言也有层叠等级。这两个层叠上下文中的层叠等级互不干扰。

同级的不一定是兄弟盒子,也可以是父子盒子;兄弟盒子也不一定等级相等;当等级相同时按 dom 树顺序从下到上堆叠。

有哪些层叠等级?

在同一个层叠上下文中,会按照下面给出顺序逐层往上堆叠。当元素创建了新的层叠上下文,它会在其层叠作用域中从头再按顺序堆叠后代。

层叠等级顺序从低到高排列如下:

  1. background-color
  2. background-image
  3. border
  4. z-index 为负数
  5. 块级普通元素
  6. float盒子
  7. inline和inline-block盒子
  8. 等位元素
  9. 不依赖 z-index的创建层叠上下文元素
  10. z-index >= 0 的元素

1~3指的是创建当前层叠上下文的元素的背景和边框。这是一个易错点:当比较层叠等级时,往往会把dom树结构上的父元素背景视为一个层叠等级,但是父元素并不是创建当前层叠上下文的元素。

正确做法是,首先确定创建当前层叠上下文的元素是什么,然后不要受dom结构的影响,按照上面给出顺序排列元素等级。这些元素中有些能够创建新的层叠上下文,这可视为一个断层,新层叠上下文中的元素先跳过,等排列完当前层叠上下文的所有元素,再去排列子层叠上下文的元素。

🌵最后

0%