CSS 層疊上下文(Stacking Context)

政採雲前端團隊發表於2019-08-29

原創不易,希望能關注下我們,再順手點個贊~~

本文首發於政採雲前端團隊部落格: CSS 層疊上下文(Stacking Context)

簡名.png

簡介

在網頁製作的過程中,元素與元素之間的位置關係,在座標軸上一般可體現為 X 軸、Y 軸和 Z 軸。對於 X 軸和 Y 軸的定位大多數開發都能比較直觀的搞清楚,而 Z 軸則相對較為模糊,或者說不能全面的理解Z 軸的顯示邏輯。

大多數人都知道可以使用 position 屬性配合 z-index 屬性解決元素的 Z 軸顯示問題,對於更深層次的原理卻不太瞭解。本文主要介紹了層疊上下文、層疊等級、層疊順序等概念。目的就是為了理清元素的 Z 軸顯示順序的內部邏輯。

一、現象

Z 軸上的顯示順序

// 穿透父級容器的 z-index
  <!-- 100 * 100 的深藍色 Block -->
  <div class="block blue" style="position: relative; z-index: auto;">
    <!-- 50 * 50 的紅色 Block -->
    <div class="small red" style="position: relative; z-index: -1;"></div>
  </div>
複製程式碼

img

// 不能穿透父級容器的 z-index
 <!-- 100 * 100 的深藍色 Block -->
  <div class="block blue" style="position: relative; z-index: 0;">
    <!-- 50 * 50 的紅色 Block -->
    <div class="small red" style="position: relative; z-index: -1;"></div>
  </div>
複製程式碼

img

兩段程式碼基本一樣,只有在深藍色盒子處有個 z-index 不同。當父級容器的 z-indexauto 的時候,紅色盒子穿過了父級容器出現在了父級容器的背後(被父級容器遮擋住)。當父級容器的 z-index0 的時候,紅色盒子無法穿過父級容器。

元素 Z 軸對比

// 元素 Z 軸對比
  <!-- 100 * 100 的深藍色盒子 -->
  <div class="block blue">
    <div style="position:relative;z-index:auto;">
      <!-- 50 * 50 的紅色盒子 -->
      <div class="small red" style="position:absolute; z-index:2;"></div>
    </div>
    <div style="position:relative;z-index:auto;">
      <!-- 50 * 50 的灰色盒子 -->
      <div class="small yellow" style="position:absolute; z-index:1; top: 10px;"></div>
    </div>
  </div>
複製程式碼

img

// 元素 Z 軸對比
  <!-- 100 * 100 的深藍色盒子 -->
  <div class="block blue">
    <div style="position:relative;z-index:0;">
      <!-- 50 * 50 的紅色盒子 -->
      <div class="small red" style="position:absolute; z-index:2;"></div>
    </div>
    <div style="position:relative;z-index:0;">
      <!-- 50 * 50 的灰色盒子 -->
      <div class="small yellow" style="position:absolute; z-index:1; top: 10px;"></div>
    </div>
  </div>
複製程式碼

img

同樣的,以上兩段程式碼基本一樣,都是有 3 層的 DIV 盒子。最外層是一個深藍色盒子,中間一層容器盒子,最下面一層紅色及灰色盒子。不同之處在於中間這層容器盒子的 z-indexauto 變成了 0。最底下的紅色及灰色盒子的 Z 軸層級比較的結果就截然不同。

由以上兩個例子我們可以發現,當 z-index 為數值並且生效的時候,容器會發生一種變化,會使得容器內的子元件無法穿過容器本身,並且子元件的層級由父元件決定。這種變化後的容器元素我們稱之為層疊上下文。

二、特性

  • 層疊上下文有幾個特性

    • 層疊上下文可以巢狀,內部層疊上下文及其所有子元素均受制於外部的層疊上下文。

這個好理解,可以參考例子 2 。當第二層的容器盒子升級為層疊上下文時,紅色盒子及灰色盒子 的 Z 軸層級受制於第二層的容器盒子。

  • 每個層疊上下文和兄弟元素獨立,也就是當進行層疊變化或渲染的時候,只需要考慮後代元素。

這一條在效能優化上可以用的上。在更新 DOM 元素的時候考慮上層疊上下文可以使得站點效能 表現更加優異。

  • 層疊上下文未指定 z-index 時,其層疊等級與 z-index : 0 相同, 要比普通元素高。指定 z-index 時按照層疊規則來。

這條專門指的由 CSS3 屬性建立出來的層疊上下文,其本身未指定 z-index。其層疊等級應該 是 z-index: 0。

三、建立

  • 層疊上下文大體上可分為三種建立方式

    • 頁面根元素,稱為根層疊上下文

    • z-index 值為數值的定位元素的傳統層疊上下文

注意:

1、z-index: auto 和 z-index: 0 在層疊等級上屬於同一級。但是 z-index: 0 就是符合這一條“z-index 為數值”會使得元素升級為層疊上下文。 2、IE6,7 有個不合常理的地方,就是當元素的 z-index 為 auto 的時候,該元素也升級為建立層疊上下文。這就是為什麼在過去 IE6/IE7 的 z-index 一直是個老大難的原因。還好現在大家可以不用考慮這兩款老舊的瀏覽器了。

  • 其他 CSS3 屬性(詳情可動手實驗瞭解)

    • z-index 值不為 autoflex 項(父元素 display : flex | inline-flex )
    • 元素的 opacity 值不是 1
    • 元素的 transform 值不是 none
    • 元素的 filter 值不是 none
    • 其他

四、兩個概念,層疊順序、層疊等級

在說層疊規則之前兩個概念需要大家瞭解一下,這有利於我們在日常交流中探討相關的問題。

  • 層疊順序( Stacking Order ),這個其實就是很字面的意思,它表示元素髮生層疊時按照特定的順序規則在 Z 軸上垂直顯示順序。
  • 層疊等級( Stacking Level ),這個很好理解了。層疊等級就是個描述元素層疊順序的一個名詞,它決定了同一個層疊上下文中元素在 Z 軸上的顯示順序。舉個例子:A 元素與 B 元素重疊之後,A 元素在 B 元素上面。那麼我們就可以直接說 A 元素的層疊等級大於 B 元素的層疊等級。

五、層疊規則

當元素互相層疊的時候,顯示規則如下。

  • 當互相層疊的元素都是層疊上下文元素,即明確的有 z-index 值的時候(沒有明確的 z-index 值的層疊上下文也就是 CSS3 建立的層疊上下文 z-index 值為0 )直接比較 z-index 的值,值大的處在值小的元素的上方。

  • 當元素處於同一層疊上下文內時可按照如下規則進行層疊判斷。

    img

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

六、招賢納士

招人,前端,隸屬政採雲前端大團隊(ZooTeam),50 餘個小夥伴正等你加入一起浪。如果你想改變一直被事折騰,希望開始能折騰事;如果你想改變一直被告誡需要多些想法,卻無從破局;如果你想改變你有能力去做成那個結果,卻不需要你;如果你想改變你想做成的事需要一個團隊去支撐,但沒你帶人的位置;如果你想改變既定的節奏,將會是“5年工作時間3年工作經驗”;如果你想改變本來悟性不錯,但總是有那一層窗戶紙的模糊… 如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望參與到隨著業務騰飛的過程,親手參與一個有著深入的業務理解、完善的技術體系、技術創造價值、影響力外溢的前端團隊的成長曆程,我覺得我們該聊聊。任何時間,等著你寫點什麼,發給 ZooTeam@cai-inc.com

七、參考文章

CSS 層疊上下文(Stacking Context)

相關文章