一、层叠上下文

层叠上下文(stacking context),是HTML中一个三维的概念。在CSS2.1标准中,每个盒模型的地位是三维的,别离是立体画布上的X轴,Y轴以及示意层叠的Z轴。个别状况下,元素在页面上沿X轴Y轴平铺,咱们觉察不到它们在Z轴上的层叠关系。而一旦元素产生重叠,这时就能发现某个元素可能笼罩了另一个元素或者被另一个元素笼罩。
如果一个元素是层叠上下文元素,咱们能够了解为这个元素在Z轴上就“出人头地”,最终体现就是它离屏幕观察者更近。

你能够把层叠上下文元素了解为了解为该元素当了官,而其余非层叠上下文元素则能够了解为普通群众。但凡“当了官的元素”就比一般元素等级要高,也就是说元素在Z轴上更靠上,更凑近观察者。

二、层叠等级

层叠等级(stacking level,叫层叠级别/层叠程度也行),决定了同一个层叠上下文中元素在z轴上的显示程序。

比如说:处于层叠上下文中的元素,就像是元素当了官,等级天然比一般元素高。再设想一下,假如一个官员A是个省级领导,他上司有一个秘书a-1,家里有一个保姆a-2。另一个官员B是一个县级领导,他上司有一个秘书b-1,家里有一个保姆b-2。a-1和b-1尽管都是秘书,然而你想一个省级领导的秘书和一个县级领导的秘书之间有可比性么?谁大谁小,谁高谁低高深莫测,所以基本没有比拟的意义。只有在A上司的a-1、a-2以及B上司的b-1、b-2中互相比拟大小高下才有意义。

分割下面说到的层叠上下文能够得出结论:
1、一般元素的层叠等级优先由其所在的层叠上下文决定。
2、层叠等级的比拟只有在以后层叠上下文元素中才有意义。不同层叠上下文中比拟层叠等级是没有意义的。

三、层叠程序

层叠程序(stacking order)示意元素产生层叠时依照特定的程序规定在Z轴上垂直显示。由此可见,后面所说的 层叠上下文层叠等级是一种概念,而这里的 层叠程序是一种规定。

当元素产生层叠时,层叠程序遵循下面图中的规定。
这里值得注意的是:
1、左上角"层叠上下文background/border"指的是层叠上下文元素的背景和边框。
2、inline/inline-block元素的层叠程序要高于block(块级)/float(浮动)元素。
3、单纯思考层叠程序,z-index: auto和z-index: 0在同一层级,但这两个属性值自身是有基本区别的。

为什么inline/inline-block元素的层叠程序要高于block(块级)/float(浮动)元素?
其实很简略,像border/background属于装璜元素的属性,浮动和块级元素个别用来页面布局,而网页设计之初最重要的就是文字内容,所以在产生层叠时会优先显示文字内容,保障其不被笼罩。

四、如何产生“层叠上下文”

后面说了那么多,到底如何产生层叠上下文呢?如何让一个元素变成层叠上下文元素呢?
其实,层叠上下文也基本上是有一些特定的CSS属性创立的,个别有3种办法:
1、HTML中的根元素<html></html>自身就具备层叠上下文,称为“根层叠上下文”。
2、一般元素设置position属性为非static值并设置z-index属性为具体数值,产生层叠上下文。
3、CSS3中的新属性也能够产生层叠上下文。

栗子1:

有两个div,p.a、p.b被包裹在一个div里,p.c被包裹在另一个div里,只为.a、.b、.c设置position和z-index属性。

<style>     div {          position: relative;          width: 100px;          height: 100px;        }        p {          position: absolute;          font-size: 20px;          width: 100px;          height: 100px;        }        .a {          background-color: pink;          z-index: 1;        }        .b {          background-color: yellow;          z-index: 2;          top: 20px;          left: 20px;        }        .c {          background-color: blue;          z-index: 3;          top: -40px;          left: 40px;        }</style>
<div>    <p class="a">a</p>    <p class="b">b</p>  </div> <div>    <p class="c">c</p>  </div>  

成果:

因为p.a、p.b、p.c三个的父元素div都没有设置z-index,所以不会产生层叠上下文,所以.a、.b、.c都处于由<html></html>标签产生的“根层叠上下文”中,属于同一个层叠上下文,此时谁的z-index值大,谁在下面。

栗子2:

有两个div,p.a、p.b被包裹在一个div里,p.c被包裹在另一个div里,同时为两个div和.a、.b、.c设置position和z-index属性。

<style>     div {          position: relative;          width: 100px;          height: 100px;        }        .box1 {        z-index: 2;      }      .box2 {        z-index: 1;      }      p {          position: absolute;          font-size: 20px;          width: 100px;          height: 100px;        }        .a {          background-color: pink;          z-index: 1;          z-index: 100;      }        .b {          background-color: yellow;          z-index: 2;          top: 20px;          left: 20px;        z-index: 200;        }        .c {          background-color: blue;          z-index: 3;          top: -40px;          left: 40px;          z-index: 999;      }    </style>
<div class="box1">    <p class="a">a</p>    <p class="b">b</p></div><div class="box2">    <p class="c">c</p></div>

成果:

尽管p.c元素的z-index值为999,远大于p.a和p.b的z-index值,然而因为p.a、p.b的父元素div.box1产生的层叠上下文的z-index的值为2,p.c的父元素div.box2所产生的层叠上下文的z-index值为1,所以p.c永远在p.a和p.b上面。
另外,因为p.a和p.b这两个元素都在父元素div.box1产生的层叠上下文中,所以谁的z-index值大,谁在下面。

栗子3:

有两个div,div.box1内有div.child1,div.box2内有div.child2,来看一看.box1/.box2的z-index属性值别离为auto和0时,.child1和child2的层级有什么不同。

<style>      .box1, .box2 {        position: relative;        z-index: auto;        color:#333;      }      .child1 {        width: 200px;        height: 100px;        background: orange;        position: absolute;        top: 0;        left: 0;        z-index: 2;      }      .child2 {        width: 100px;        height: 200px;        background: pink;        position: absolute;        top: 20px;        left: 0;        z-index: 1;      }    </style>
<div class="box1">  <div class="child1">child1</div></div><div class="box2">  <div class="child2">child2</div></div>
  • .box1/.box2的z-index=auto时成果:
  • .box1/.box2的z-index=0时成果:

1、.box1/.box2尽管设置了position: relative,然而z-index: auto的状况下,这两个div还是一般元素,并没有产生层叠上下文。所以,child1/.child2属于<html></html>元素的“根层叠上下文”中,此时,谁的z-index值大,谁在下面。
2、而把.box1/.box2的z-index属性值改为0,最终后果齐全相同。这时.child2笼罩在了.child1下面。起因是什么呢?因为设置z-index: 0后,.box1/.box2产生了各自的层叠上下文,这时候要比拟.child1/.child2的层叠关系齐全由父元素.box1/.box2的层叠关系决定。然而.box1/.box2的z-index值都为0,都是块级元素(所以它们的层叠等级,层叠程序是雷同的),这种状况下,在DOM构造中前面的笼罩后面的,所以.child2就在下面。

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

CSS3中呈现了很多新属性,其中一些属性对层叠上下文也产生了很大的影响。如下:

父元素的display属性值为flex|inline-flex,子元素z-index属性值不为auto的时候,子元素为层叠上下文元素;
元素的opacity属性值不是1;
元素的transform属性值不是none;
元素mix-blend-mode属性值不是normal;
元素的filter属性值不是none;
元素的isolation属性值是isolate;
will-change指定的属性值为下面任意一个;
元素的-webkit-overflow-scrolling属性值设置为touch。

CSS3中,元素属性满足以上条件之一,就会产生层叠上下文。咱们用第1条来做一个简略的解释阐明。

栗子4:

栗子有三个层级:div.box > div.parent > div.child
咱们来看一下,给div.box设置CSS3属性display=flex对层级有什么影响。

<style>     .box {     }     .parent {        width: 200px;        height: 100px;        background: yellow;        /* 尽管设置了z-index,然而没有设置position,z-index有效,.parent还是一般元素,没有产生层叠上下文 */        z-index: 1;      }      .child {        width: 100px;        height: 200px;        background: purple;        position: relative;        z-index: -1;      }</style>
<div class="box">  <div class="parent">    parent    <div class="child">child</div>  </div></div>


1、.parent设置了z-index属性值,然而没有设置position属性,z-index有效,所以没有产生层叠上下文,.parent还是一般的块级元素。此时,在层叠程序规定中,z-index值小于0的.child会被一般的block块级元素.parent笼罩。
2、当给.box设置display: flex时,.parent就变成层叠上下文元素,依据层叠程序规定,层叠上下文元素的background/border的层叠等级小于z-index值小于0的元素的层叠等级,所以z-index值为-1的.child在.parent下面。

总结:

下面说了那么多,可能你还是有点懵。这么多概念规定,来点最理论的,有没有一个“套路”当遇到元素层叠时,能很清晰地判断出他们谁在上谁在下呢?答案是——必定有啊!

1、首先先看要比拟的两个元素是否处于同一个层叠上下文中:
      1.1如果是,谁的层叠等级大,谁在下面(怎么判断层叠等级大小呢?——看“层叠程序”图)。
      1.2如果两个元素不在对立层叠上下文中,请先比拟他们所处的层叠上下文的层叠等级。
2、当两个元素层叠等级雷同、层叠程序雷同时,在DOM构造中前面的元素层叠等级在后面元素之上。