Skip to main content

层叠上下文

关于 z-index

z-index 这个属性并不是在任何元素上都具有效果,只有其定位样式属性 position 不等于 static 时,才会生效。

另外,判断一个元素在 z 轴上的 堆叠顺序,不仅仅是比较元素的 z-index 值大小,这个 堆叠顺序 实际上由 层叠上下文层叠等级 共同决定。

层叠等级

层叠等级英文称作 "stacking level",其决定了同一个层叠上下文中元素在 z 轴上的 堆叠顺序。在同一个层叠上下文中,内部子元素的层叠顺序可以参考下面的规则。

  • 层叠上下文容器的 background/border 是处于最低层叠顺序
  • 其次是 z-index < 0 的子元素
  • 如果 z-index 缺省或者显示定义为 z-index:0 | auto 或者 z-index 取值相同,那么有 block < float < inline-block = inline
  • 最后是 z-index 谁大谁就处于上方

pic.nm

下面这两个是层叠领域的黄金准则。当元素发生层叠的时候,其覆盖关系遵循下面 3 个准则:

  1. 谁大谁上:当具有明显的层叠等级标示的时候,如识别的 z-indx 值,在同一个层叠上下文领域,层叠等级值大的那一个覆盖小的那一个
  2. 后来居上:当元素的 层叠等级一致层叠顺序相同 的时候,在 DOM流 中处于后面的元素会覆盖前面的元素
  3. 如果 z-index 缺省或者显示定义为 z-index:0 | auto 或者 z-index 取值相同,那么有 block < float < inline-block = inline
你需要的 "套路"

上面说了这么多,可能你还是有点懵,下面梳理一下当遇到元素层叠时,我们怎么能很清晰地判断出他们谁在上谁在下。

  • 首先比较两个元素是否位于同一个层叠上下文中
    • 如果在同一个层叠上下文,那么根据上面的准则来比较
    • 如果不在同一个层叠上下文,那么它们的层叠顺序 取决于位于同一个层叠上下文的祖先元素的层叠顺序 决定
  • 当两个元素层叠等级相同、层叠顺序相同时,在 DOM 结构中后面的元素层叠等级在前面元素之上

层叠上下文

层叠上下文和块级格式上下文(BFC)类似,都具有上下文这个概念,通俗来讲就是具有某种特性或者规则的 "作用域"。

层叠上下文是由具有特定 CSS 属性的元素创建的,它的作用就是决定该元素及其内部

层叠上下文的创建

  • <html> 根元素本身具有一个根层叠上下文
  • 普通元素设置 position 属性为非 static 并设置 z-index 属性为 具体数值(不能是 auto),产生层叠上下文
  • CSS3 中的某些属性也会产生层叠上下文(详见后文)

层叠上下文的例子

  • div#1div#2div#3 是处于同一个根元素的层叠上下文中的
  • div#4div#5div#6 是处于 div#3 创建的层叠上下文中的

pic

div#1div#3 处于同一个层叠上下文中,此时直接比较它们层叠顺序,z-index: 5 大于 z-index: 4,所以 div#1 是位于 div#3 上方的。

div#1div#4 位于不同的层叠上下文,但是 div#1div#4 的父元素是处于同一个层叠上下文中,并且 div#1 的层叠顺序是大于 div#4 的父元素的层叠顺序,因此就算 div#4z-index 大于 div#1z-indexdiv#4 依旧位于其下方。

下面继续来看一个例子。

<div style="position:relative; z-index:auto;">
<img src="mm1.jpg" style="position:absolute; z-index:2;">
</div>
<div style="position:relative; z-index:auto;">
<img src="mm2.jpg" style="position:relative; z-index:1;">
</div>

图片1 和图片 2 的父元素都不会产生新的层叠上下文,因为它们的 z-index 取值为 auto,所以两张图片是位于同一个根层叠上下文中的,前者的 z-index 大于后者,所以图片1 位于图片 2 上方。

下面将这两个图片的父元素修改一下,让其能够产生层叠顺序相同的层叠上下文。

<div style="position:relative; z-index:0;">
<img src="mm1.jpg" style="position:absolute; z-index:2;">
</div>
<div style="position:relative; z-index:0;">
<img src="mm2.jpg" style="position:relative; z-index:1;">
</div>

由于这两张图片不位于同一个层叠上下文,所以它们的 层叠顺序取决于位于同一个层叠上下文的父元素的层叠顺序,这两个父元素层叠顺序相同,所以在 DOM 树考后的那个父元素会位于前面那个父元素上方,此时图片 2 就位于 图片 1 上方了。

CSS3 属性对层叠上下文的影响

CSS3的出现除了带来了新属性,同时还对过去的很多规则发出了挑战,特别是层叠上下文这一块的影响要更加广泛与显著。

如下:

  1. z-index 值不为 autoflex项(父元素 display: flex | inline-flex
  2. 元素的 opacity 值不是 1
  3. 元素的 transform 值不是 none
  4. 元素 mix-blend-mode 值不是 normal
  5. 元素的 filter 值不是 none
  6. 元素的 isolation 值是 isolate
  7. will-change 指定的属性值为上面任意一个
  8. 元素的 -webkit-overflow-scrolling 设为 touch

下面会挑几个常用的来讲。

弹性布局与层叠上下文

对于弹性合作的子项,其 z-index 只要是数值(不需要 position),就会产生新的层叠上下文。

transform、opacity 和 will-change 与层叠上下文

transformopacitywill-change 只要不是默认值,那么该元素就会产生新的层叠上下文。

层叠上下文对鼠标事件的影响

z-index大的会覆盖小的hover

pointer-events: none 可以无视

Reference