天天看點

css面試點-css層疊上下文

什麼是層疊上下文

  • 層疊上下文(

    stacking context

    ),是

    HTML

    中一個三維的概念。在

    CSS2.1

    規範中,每個盒模型的位置是三維的,分别是平面畫布上的X軸,Y軸以及表示層疊的Z軸。一般情況下,元素在頁面上沿X軸Y軸平鋪,我們察覺不到它們在Z軸上的層疊關系。而一旦元素發生堆疊,這時就能發現某個元素可能覆寫了另一個元素或者被另一個元素覆寫。
  • 如果一個元素含有層疊上下文,(也就是說它是層疊上下文元素),我們可以了解為這個元素在Z軸上就“高人一等”,最終表現就是它離螢幕觀察者更近。

什麼是層疊等級(層疊級别or層疊水準)

  • 在同一個層疊上下文中,它描述定義的是該層疊上下文中的層疊上下文元素在Z軸上的上下順序。
  • 在其他普通元素中,它描述定義的是這些普通元素在Z軸上的上下順序。

一些注意點

  • 首先,z-index屬性值并不是在任何元素上都有效果。它僅在定位元素(定義了position屬性,且屬性值為非static值的元素)上有效果。
  • 判斷元素在Z軸上的堆疊順序,不僅僅是直接比較兩個元素的z-index值的大小,這個堆疊順序實際由元素的層疊上下文、層疊等級共同決定。
  • 普通元素的層疊等級優先由其所在的層疊上下文決定。

如何産生層疊上下文

  • HTML中的根元素本身j就具有層疊上下文,稱為“根層疊上下文”。
  • 普通元素設定position屬性為非static值并設定z-index屬性為具體數值,産生層疊上下文。
  • CSS3中的新屬性也可以産生層疊上下文。

例一:

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

<body>  
  <div>  
    <p class="a">a</p>  
    <p class="b">b</p>  
  </div> 

  <div>  
    <p class="c">c</p>  
  </div>  
</body> 
           

效果圖如下

css面試點-css層疊上下文

因為p.a、p.b、p.c三個的父元素div都沒有設定z-index,是以不會産生層疊上下文,是以.a、.b、.c都處于由标簽産生的“根層疊上下文”中,屬于同一個層疊上下文,此時誰的z-index值大,誰在上面。

例二

<style>
  div {
    width: 100px;
    height: 100px;
    position: relative;
  }
  .box1 {
    z-index: 2;
  }
  .box2 {
    z-index: 1;
  }
  p {
    position: absolute;
    font-size: 20px;
    width: 100px;
    height: 100px;
  }
  .a {
    background-color: blue;
    z-index: 100;
  }
  .b {
    background-color: green;
    top: 20px;
    left: 20px;
    z-index: 200;
  }
  .c {
    background-color: red;
    top: -20px;
    left: 40px;
    z-index: 9999;
  }
</style>

<body>
  <div class="box1">
    <p class="a">a</p>
    <p class="b">b</p>
  </div>

  <div class="box2">
    <p class="c">c</p>
  </div>
</body>
           

效果圖如下

css面試點-css層疊上下文

雖然p.c元素的z-index值為9999,遠大于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下面。

什麼是層疊順序

表示元素發生層疊時按照特定的順序規則在Z軸上垂直顯示。

css面試點-css層疊上下文

不同屬性的元素的層疊順序

需要注意的

  • 左上角"層疊上下文

    background/border

    "指的是層疊上下文元素的背景和邊框。
  • inline/inline-block

    元素的層疊順序要高于

    block

    (塊級)/

    float

    (浮動)元素。
  • 單純考慮層疊順序,

    z-index: auto

    z-index: 0

    在同一層級,但這兩個屬性值本身是有根本差別的。
<style>
  .box1, .box2 {
    position: relative;
    z-index: auto;
  }
  .child1 {
    width: 200px;
    height: 100px;
    background: #168bf5;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
  }
  .child2 {
    width: 100px;
    height: 200px;
    background: #32c292;
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
  }
</style>
</head>

<body>
  <div class="box1">
    <div class="child1"></div>
  </div>

  <div class="box2">
    <div class="child2"></div>
  </div>
</body>
           
css面試點-css層疊上下文

說明:.box1/.box2雖然設定了position: relative,但是z-index: auto的情況下,這兩個div還是普通元素,并沒有産生層疊上下文。是以,child1/.child2屬于元素的“根層疊上下文”中,此時,誰的z-index值大,誰在上面。

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。

例一

<style>
  .box {
  }
  .parent {
    width: 200px;
    height: 100px;
    background: #168bf5;
    /* 雖然設定了z-index,但是沒有設定position,z-index無效,.parent還是普通元素,沒有産生層疊上下文 */
    z-index: 1;
  }
  .child {
    width: 100px;
    height: 200px;
    background: #32d19c;
    position: relative;
    z-index: -1;
  }
</style>
</head>

<body>
  <div class="box">
    <div class="parent">
      parent
      <div class="child">child</div>
    </div>
  </div>
</body>
           
css面試點-css層疊上下文

說明: 我們發現,.child被.parent覆寫了。按照“套路”來分析一下: 雖然.parent設定了z-index屬性值,但是沒有設定position屬性,z-index無效,是以沒有産生層疊上下文,.parent還是普通的塊級元素。此時,在層疊順序規則中,z-index值小于0的.child會被普通的block塊級元素.parent覆寫。

對于上面的栗子,我們隻修改.box的屬性,設定display: flex,其餘屬性和DOM結構不變。

.box {
  display: flex;
}
           
css面試點-css層疊上下文

說明: 當給.box設定display: flex時,.parent就變成層疊上下文元素,根據層疊順序規則,層疊上下文元素的background/border的層疊等級小于z-index值小于0的元素的層疊等級,是以z-index值為-1的.child在.parent上面。