前端必須掌握的「CSS層疊上下文」講解 | 純手工示例,包教包會

大家都不看的總集篇: 從零開始的大前端築基之旅(深刻淺出,持續更新~)
以爲不錯就順手點個贊吧css

本文中全部示例均爲 `html` 渲染構成,因此能夠直接選中示例在控制檯調試,推薦本身動手試試文章中列舉的小提示,有助於加深理解 。有任何問題歡迎在評論中指出。 html

嗯。。。chrome --> 鼠標移動到示例上 --> 右擊 --> 檢查前端

大部分人在初步學完css後,對z-index的印象大概處於「z-index就是用來描述定義一個元素在屏幕Z軸上的堆疊順序」。例如,若是A元素和B元素重疊了,這麼說有點枯燥,換個說法,css3

  1. 若是漂亮妹子A和文字B註釋重疊了
  2. 可是頁面渲染的時候,文字處於圖片之上,擋住你看妹子了
  3. 這時候,你可能會
    • 設置妹子的z-index爲999
    • 設置文字的z-index爲-1

就是這麼差異對待。既然拿上面那一段舉栗子,那就表明這種理解有問題,至少是不嚴謹的。web

  1. z-index屬性僅在定位元素(定義了position屬性,且屬性值爲非static值的元素)上有效果。chrome

  2. 元素在Z軸上的堆疊順序,由元素所屬的層疊上下文、元素的層疊水平、以及元素在文檔中的順序等共同決定,元素的z-index值的只是決定元素的層疊水平的條件之一。瀏覽器

這兩條必定要記牢,下面會用到。markdown

什麼是「層疊上下文」

層疊上下文(stacking context),是HTML中一個三維的概念。它劃分了某種領域或範圍,在渲染規則層面,將內部與外部隔開,並賦予元素自身及內部區域某些特性。編輯器

在CSS2.1規範中,每一個盒模型的位置是三維的,即元素除了在頁面上沿X軸Y軸平鋪,同時還擁有一個相對屏幕垂直的縱深,也就是表示層疊的Z軸wordpress

對於元素所展示的內容,通常狀況下,元素在文檔中順序排列,互相排斥,咱們察覺不到它們在Z軸上的層疊關係。而一旦元素髮生堆疊,就會發現某個元素覆蓋了另外一個元素或者被另外一個元素覆蓋。

對於元素的層級結構來講,父元素與其子元素大部分狀況下都是重疊的,只是通常狀況下,父元素沒有設置邊框和背景,或者由於子元素沒有突破父元素的寬高,咱們通常也不會意識到元素的堆疊狀況。

元素因爲特定的css設置,擁有了層疊上下文後,就會變成層疊上下文元素;

層疊上下文元素有以下特性:

  1. 層疊上下文的層疊水平要比普通元素高;
  2. 層疊上下文能夠嵌套,內部層疊上下文及其全部子元素均受制於外部的層疊上下文。
  3. 每一個層疊上下文是自成體系的,當元素髮生層疊的時候,整個元素被認爲是在父層疊上下文的層疊順序中。
  4. 每一個層疊上下文和兄弟元素獨立,也就是當進行層疊變化或渲染的時候,只須要考慮後代元素。
  5. 層疊上下文能夠阻斷元素的混合模式;

如何建立「層疊上下文」

層疊上下文大部分由一些特定的CSS屬性建立。

  1. HTML中的根元素<html></html>自己就具備層疊上下文,稱爲「根層疊上下文」。
  2. 普通元素設置position屬性爲static值並設置z-index屬性爲具體數值,產生層疊上下文。
  3. css3補充了一些建立層疊上下文的條件,後面會列舉。

層疊水平

層疊水平(stacking level),決定了同一個層疊上下文中元素在z軸上的顯示順序。

全部的元素都有層疊水平,包括層疊上下文元素。每一個層疊上下文和兄弟元素獨立,所以層疊水平的比較只有在當前層疊上下文元素中才有意義。

歸屬於不一樣層疊上下文的元素,首先要追溯其祖先元素的層疊上下文,直到各自的祖先層疊上下文元素歸屬於同一個層疊上下文,而後判斷這兩個祖先元素的層疊水平。

層疊順序

層疊順序(stacking order), 表示元素髮生層疊時的特定的垂直顯示順序,是一種用於肯定元素層疊水平的規則。

當元素重疊時,必須決定哪部份內容展現在屏幕上,所以,層疊順序決定了一條優先級規則,也能夠稱爲等級鏈規則。 如下排名分前後,自上而下優先級愈來愈低:

  1. z-index > 0 (要求z-index屬性生效)
  2. z-index: auto 或者 z-index: 0 (z-index: auto 不會建立層疊上下文)
  3. inline、inline-block 行內盒子
  4. float浮動盒子
  5. block塊級盒子,非 inline-block,無 position 定位(static除外)的子元素
  6. z-index < 0
  7. 層疊上下文元素的 background/border

當元素髮生層疊的時候,其覆蓋關係一般遵循下面2個準則:

  1. 在同一個層疊上下文領域,當具備明顯的層疊水平標示的時候,若有效的 z-index 值,層疊水平值大的那一個覆蓋小的那一個。
  2. 當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處於後面的元素會覆蓋前面的元素。

深刻淺出

概念講解完了,下面進入實戰環節,來,看我手上,如今咱們有兩隻貓:

驗證準則2,

當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處於後面的元素會覆蓋前面的元素。

而後讓它們重疊起來:

<div class="container">
  <div class="black">
    <img src="black.jpg"></img>  
  </div>
<div class="white">
    <img src="white.jpg"></img>  
  </div>
</div>
複製代碼
.container{
  width: 300px;
  height: 200px;
  border: 1px solid grey;
}

.black{
  position: absolute;
}

.white{
  position: absolute;
  top: 50px;
  left: 50px;
}
複製代碼

當前 black.imgwhite.img 都是普通元素, 其父元素也是普通元素,所以二者處於元素的「根層疊上下文」中。而且層疊水平一致,所以遵循後來居上原則,白貓覆蓋黑貓。

驗證準則1

在同一個層疊上下文領域,當具備明顯的層疊水平標示的時候,若有效的 z-index 值,層疊水平值大的那一個覆蓋小的那一個。

給黑貓black.img增長 z-index 屬性並設置 position 使其生效

.black img{
  position: relative;
  z-index: 1;
}
複製代碼

當前 black.img 是層疊上下文元素(不影響比較層疊水平), white.img 是普通元素, 其父元素都是普通元素,所以二者處於元素的「根層疊上下文」中。black.img 具備明顯的層疊水平標示 z-index: 1。所以黑貓覆蓋了白貓。

驗證特性二、3

  1. 層疊上下文能夠嵌套,內部層疊上下文及其全部子元素均受制於外部的層疊上下文。
  2. 每一個層疊上下文是自成體系的,當元素髮生層疊的時候,整個元素被認爲是在父層疊上下文的層疊順序中。

歸屬於不一樣層疊上下文的元素,首先要追溯其祖先層疊上下文元素,直到各自的祖先層疊上下文元素歸屬於同一個層疊上下文,而後判斷這兩個祖先元素的層疊水平。

接上面代碼,首先給白貓white.img增長 z-index 屬性並設置 position 使其生效,當前css代碼以下:

.container{
  width: 300px;
  height: 200px;
  border: 1px solid grey;
}

.black{
  position: absolute;
}
.black img{
  position: relative;
  z-index: 1;
}

.white{
  position: absolute;
  top: 50px;
  left: 50px;
}

.white img{
  position: relative;
   z-index: 2;
}
複製代碼

此時,black.imgwhite.img 都是層疊上下文元素(不影響層疊水平對比), 其父元素都是普通元素,二者處於元素的「根層疊上下文」中。black.imgwhite.img都具備明顯的層疊水平標示 z-index,白貓的 z-index 值大於黑貓,因而從新覆蓋在黑貓上面。

blackwhite補充z-index 屬性,使blackwhite產生層疊上下文

.black{
  position: absolute;
  z-index: 2;
}
.white{
  position: absolute;
  top: 50px;
  left: 50px;
  z-index: 1;
}
複製代碼

雖然白貓的 z-index 值大於黑貓,但因爲各自的父元素均爲層疊上下文元素,所以白貓和黑貓歸屬於不一樣的上下文元素,沒法直接比較,須要追溯各自父元素。

blackwhite處於元素的「根層疊上下文」中,blackz-index 大於 white,所以black的後代元素black.img覆蓋在white的後代元素white.img上,即黑貓覆蓋白貓。

驗證特性1

  1. 層疊上下文的層疊水平要比普通元素高;

爲了使兩張圖片重疊,設置black的寬高爲0。

若是繼續使用position: absolute來使圖片重疊,就無法驗證本條,由於依據層疊順序z-index: 0z-index: auto 自己就比inlineblock優先級高,體現不出層疊上下文元素比普通元素層疊水平高

html代碼不變,css以下

.black{
  width :0;
  height :0;
}
// markdown 編輯器可能會補充一些屬性,致使黑貓沒法顯示,所以咱們補充下面屬性
.black img{
  width: 232px;
  height: 153px;
  max-width: inherit; 
}
複製代碼

上面的示例中,白貓和黑貓都是普通元素,處於元素的「根層疊上下文」中,其中白貓在DOM流中處於後面,所以白貓在黑貓的上面。

下面咱們使用css3中補充的建立上下文的條件來使black元素產生層疊上下文。

元素的opacity屬性值不是1

.black{
  width :0;
  height :0;
  opacity: 0.9;
}
複製代碼

如今, black 元素是層疊上下文元素,其後代black.img的層疊水平大於普通元素,因此黑貓覆蓋了白貓。若是你仔細看,仍是能夠看到黑色背景後面的白貓的。

驗證層疊順序:z-index: auto > inline/inline-block

上個示例提到, z-index: 0z-index: auto 自己就比inlineblock優先級高,咱們來驗證一下。總體css屬性以下。

.black img{
  position: absolute;
}
複製代碼

僅設置black.imgposition: absolute;。不顯式設置 z-index 數值時,瀏覽器會默認z-index: auto

當前 black.imgwhite.img 都是普通元素(z-index: auto 不會建立層疊上下文), 其父元素也是普通元素,所以二者處於元素的「根層疊上下文」中。元素無明顯的層疊水平標示 z-index,依據層疊順序,z-index: auto > inline/inline-block,黑貓在上面。

若是對白貓 white.img 追加position: absolute; 屬性,black.imgwhite.img 就處於同一層疊水平,依據後來居上原則,白貓在上面。選中本示例在控制檯中調試一下吧

驗證層疊順序:z-index < 0 > 層疊上下文元素的 background/border

在此以前,咱們先驗證另外一個規則:block塊級盒子 > z-index < 0 如今,你只有黑貓了。

<div class="container">
  <div class="black">
    <img src="black.jpg"></img>  
  </div>
</div>
複製代碼

black設置背景色橙色, black.img 設置z-index: -1

.black{
  background: orange;
}
.black img{
  position: relative;
  z-index: -1;
}
複製代碼

整個black元素都顯示橙色,證實了塊級元素的層疊水平比z-index: -1 高。 而後給black元素追加opacity: 0.9,使black產生層疊上下文。

.black{
  background: orange;
  opacity: 0.9;
}
.black img{
  position: relative;
  z-index: -1;
}
複製代碼

此時,圖片出如今橙色背景之上,驗證了z-index < 0 > 層疊上下文元素的 background/border

css3產生層疊上下文的規則

在CSS3中,元素屬性知足如下條件之一,也會產生層疊上下文。

  1. 父元素的display屬性值爲flex|inline-flex,子元素z-index屬性值不爲auto的時候,子元素爲層疊上下文元素(此時z-index會生效,不須要設置position);
  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`。

4-8條可自行百度或點擊參考文檔1

驗證css3規則1

父元素的display屬性值爲flex|inline-flex,子元素z-index屬性值不爲auto的時候,子元素爲層疊上下文元素(此時z-index會生效,不須要設置position);

<div class="container">
  <div class="black">
    <img src="black.jpg"></img>  
  </div>
</div>
複製代碼

black設置背景色橙色, black.img 設置z-index: -1

.black{
  background: orange;
}
.black img{
  position: relative;
  z-index: -1;
}
複製代碼

使用規則1,補充css屬性以下:

.container{
  width: 300px;
  height: 200px;
  border: 1px solid grey;
  display: flex;
}
.black{
  background: orange;
  z-index:2; 
}
複製代碼

此時,圖片出如今橙色背景之上,依據層疊順序z-index < 0 > 層疊上下文元素的 background/border,反向推出此時black爲層疊上下文元素。

白貓還你

如今,把白貓還給你,使用下面的示例在控制檯驗證一下各項規則和你的想法吧

嗯。。。chrome --> 鼠標移動到示例上 --> 右擊 --> 檢查

若是你收穫了新知識,或者收穫了左側精美圖片,請點個吧~

-

總集篇: 從零開始的大前端築基之旅(深刻淺出,持續更新~)

推薦閱讀:

參考文章:

  1. 深刻理解CSS中的層疊上下文和層疊順序
相關文章
相關標籤/搜索