1

本文是我学习层叠上下文的总结。主要从以下途径学习:
MDN: https://developer.mozilla.org...
张鑫旭大大的博文:http://www.zhangxinxu.com/wor...

层叠顺序

层叠顺序遵循下图的规则,其中在张鑫旭大大的博文中提到inline-block的层叠顺序与图中inline box是一个level的;z-index:auto实际上和z-index:0单纯从层叠水平上看,可以认为是同一level(两者在层叠上下文领域有着根本性的差异)。(如要看完整图片请移步到张鑫旭大大博文

层叠上下文

层叠准则

  1. 根据上图,层叠水平越大,就显示在越上面。

  2. 当层叠水平一样时,在DOM中位置越后,就显示在越上面。

层叠上下文的特性

  • 层叠上下文的层叠水平比普通元素高;

  • 层叠上下文可以嵌套,内部层叠上下文及其所有子元素都受限于外部的层叠上下文;

  • 层叠上下文和兄弟元素独立,只需要考虑后代元素;

  • 每个层叠上下文是自包含的:当元素的内容发生层叠后,整个该元素将会 在父层叠上下文中 按顺序进行层叠。

层叠上下文创建的条件

  1. html元素

  2. z-index的值不为auto的相对/绝对定位元素

  3. position: fixed的元素

  4. 应用了某些CSS3的元素

    • z-index的值不为auto的flex项(即父元素display: flex | inline-flex)

    • opacity小于1的元素

    • transform值不为none元素

    • min-blend-mode值不为none的元素

    • filter值不为none的元素

    • perspective值不为none的元素

    • isloation值为isolate的元素

    • will-change指定了任意属性

    • -webkit-overflow-scrolling值为touch的元素

demo

先放MDN的例子的效果图(点击查看代码与效果

图片描述

下面是我自己写的一些demo,主要与z-index属性相关。

demo通用HTML代码


    <div class="outter">outter
      <div class="inner">inner</div>
    </div>

基础CSS(没有创建层叠上下文)。所有demo都是在这份CSS的基础上写出来的。


    .outter {
        width: 200px;height: 300px;background: red;
    }
    
    .inner {
      position: relative; z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

inner被outter覆盖

当outter的position值为relative或absolute,并且不设置z-index值或者z-index值为auto时,outter没有创建层叠上下文。此时根据层叠顺序表,负的z-index元素在block元素下面,所以,inner被outter覆盖了。
查看demo

相对/绝对定位


    .outter {
      position: relative;z-index: auto;
      
      width: 200px;height: 300px;background: red;
    }
    
    .inner {
      position: relative; z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

基础demo

虽然outter的position值设置为absolute或者relative,但z-index值设置为auto,此时,outter并没有创建层叠上下文,所以,效果与基础demo一致。
查看demo


    .outter {
      position: relative;z-index: 0;
      
      width: 200px;height: 300px;background: red;
    }
    
    .inner {
      position: relative; z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

outter被inner覆盖

当outter的z-index值设置为数值,甚至为0时,outter会创建层叠上下文,此时inner会覆盖outter。
查看demo

position: fixed的元素

    .outter {
      position: fixed;
      
      width: 200px;height: 300px;background: red;color: #fff;
    }
    
    .inner {
      position: relative;z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

outter被inner覆盖

当outter的position值设置为fixed时,outter会创建层叠上下文,此时inner会覆盖outter。
查看demo

opacity小于1的元素

    .outter {
      opacity: .5;
      
      width: 200px;height: 300px;background: red;color: #fff;
    }
    
    .inner {
      position: relative;z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

outter被inner覆盖

当outter的opacity值设置小于1时,outter会创建层叠上下文,此时inner会覆盖outter。
查看demo

transform值不为none元素

    .outter {
      transform: rotate(15deg);
      
      width: 200px;height: 300px;background: red;color: #fff;
    }
    
    .inner {
      position: relative;z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

outter被inner覆盖

当outter的opacity值设置不为none时,outter会创建层叠上下文,此时inner会覆盖outter。
查看demo

will-change指定了任意属性

   .outter {
      will-change: transform; 
      
      width: 200px;height: 300px;background: red;color: #fff;
    }
    
    .inner {
      position: relative;z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

outter被inner覆盖

当outter的will-change值设置为任何值时,outter会创建层叠上下文,此时inner会覆盖outter。
查看demo

z-index的值不为auto的flex项(即父元素display: flex | inline-flex)

此处的HTML结构有点不同。

<div class="box">
  <div class="outter">outter
    <div class="inner">inner</div>
  </div>
</div>

    .box {
      display: flex;
    }
    .outter {
      z-index: 1;
      
      width: 200px;height: 300px;background: red;color: #fff;
    }
    
    .inner {
      position: relative;z-index: -1;
      
      width: 300px;height: 200px;background: blue;
    }

outter被inner覆盖

在原来的HTML外层加一个class为box的div,并设置display值为flex或者inline-flex,此时outter为flex项,会创建层叠上下文,此时inner会覆盖outter。
查看demo

其他
由于暂时对mix-blend-mode、filter、isolation、-webkit-overflow-scrolling属性了解不多,所以没有做demo。如果想看demo效果,可以看张鑫旭大大的博文

结语

学习了层叠上下文之后,对于元素覆盖这个问题有了比较清晰的认识,有时候可以不依赖z-index来解决问题了。


chenBright
817 声望57 粉丝

学习算法、C++、linux…