# CSS 中的层叠顺序

作者:魏聪 时间:2020-01-13

# 前言

CSS 中元素是有层叠顺序的,一般情况下,我们不需要区分元素的层叠顺序,当元素发生冲突的时候,比如元素之间有交集,那就需要区分谁显示上面,谁显示在下方了。那么在 CSS 世界中,元素的层叠顺序是怎样的呢?这里我们需要了解这两个概念:层叠上下文和层叠顺序。

# 1、层叠上下文

层叠上下文(stacking context),在 HTML 中其实是一个三维的概念,如果元素含有层叠上下文,我们可以理解这个元素具有特殊性,在显示上高人一等。它跟 BFC 其实是类似的,只不过它和普通元素放在一起表现的是在显示上优先显示。

# 2、层叠水平

层叠水平(stacking level),它决定了同一个层叠上下文中元素在 Z 轴上的显示顺序,同一个层叠上下中也需要进行排序的,并且所有元素都有层叠水平,包括层叠上下文元素,需要注意的是:对于普通元素的层叠水平,只有在当前层叠上下文元素才有意义。这是因为普通元素的层叠水平由层叠上下文决定,所以在不同层叠上下文的普通元素先比较的是层叠上下文的层叠水平,同一层叠上下文的普通元素,此时比较的是普通元素的层叠水平。

# 3、层叠顺序

层叠顺序(stacking order),它表示元素发生层叠的时候,垂直显示的规则。它跟层叠上下文和层叠水平不同,层叠上下文和层叠水平是概念,但它是一个规则。它的层叠顺序规则如图:

此外还有两个层叠准则:

  • 谁大谁上 当具有明显的层叠水平标识的时候,比如 z-index,同处于一个层叠上下文领域,层叠水平大的优先显示
  • 后来居上 当元素层叠水平一致,层叠顺序相同时,DOM 流后面会优先显示

# 4、层叠上下文的特性

  • 层叠上下文的层叠水平要比普通元素高
  • 层叠上下文可以阻断元素的混合模式
  • 层叠上下文可以嵌套,内部层叠上下文以及其子元素均受制于外部层叠上下文
  • 每个层叠上下文和兄弟元素独立,当进行层叠变化和渲染时,只需要考虑子元素
  • 每个层叠上下文自成体系,当元素发生层叠的时候,整个元素被认为是在父层叠上下文的层叠顺序中

# 5、创建层叠上下文

  • 页面根元素本身是一个层叠上下文元素
  • 带有 z-index 不为默认值 auto 的定位元素
  • z-index 不为默认值 auto 的 flex 项(父元素 flex | inline-flex)

需要两个条件:父级元素需要是 flex 元素;子元素的 z-index 不是 auto,那么子元素是层叠上下文元素

  • 元素的 opacity 不为 1
  • 元素的 transform 值不是 none
  • 元素的 mix-blend-mode 值不是 normal
  • 元素的 filter 值不是 none
  • 元素的 isolation 值是 isolate
  • will-change 指定的属性值为上面任意一个
  • 元素的-webkit-overflow-scrolling 为 touch

# 6、层叠上下文和层叠顺序

  • 1、如果层叠上下文元素不依赖 z-index 值,那么它的层叠顺序 z-index:auto 可以看作 z-index:0 级别
  • 2、如果层叠上下文元素依赖 z-index 数值,那么它的层叠顺序由 z-index 数值决定