什么是層疊上下文?如何形層疊上下文?層疊順序是怎樣的?


CSS2.1規范中,每個盒模型的位置是三維的,分別是平面畫布上的x軸,y軸以及表示層疊的z軸。層疊上下文即元素在某個層級上z軸方向的排列關系。

那么這里有幾個重要的概念:層疊上下文 (堆疊上下文, Stacking Context)、層疊等級 (層疊水平, Stacking Level)、層疊順序 (層疊次序, 堆疊順序, Stacking Order)、z-index。

1. 層疊上下文 (Stacking Context)

文章<關於z-index 那些你不知道的事>有一個很好的比喻,這里引用一下;

可以想象一張桌子,上面有一堆物品,這張桌子就代表着一個層疊上下文。 如果在第一張桌子旁還有第二張桌子,那第二張桌子就代表着另一個層疊上下文。

現在想象在第一張桌子上有四個小方塊,他們都直接放在桌子上。 在這四個小方塊之上有一片玻璃,而在玻璃片上有一盤水果。 這些方塊、玻璃片、水果盤,各自都代表着層疊上下文中一個不同的層疊層,而這個層疊上下文就是桌子。

每一個網頁都有一個默認的層疊上下文。 這個層疊上下文(桌子)的根源就是 <html></html>。 html標簽中的一切都被置於這個默認的層疊上下文的一個層疊層上(物品放在桌子上)。

當你給一個定位元素賦予了除 auto 外的 z-index 值時,你就創建了一個新的層疊上下文,其中有着獨立於頁面上其他層疊上下文和層疊層的層疊層, 這就相當於你把另一張桌子帶到了房間里。

層疊上下文1 (Stacking Context 1)是由文檔根元素形成的, 層疊上下文2和3 (Stacking Context 2, 3) 都是層疊上下文1 (Stacking Context 1) 上的層疊層。 他們各自也都形成了新的層疊上下文,其中包含着新的層疊層。

在層疊上下文中,其子元素按照上面解釋的規則進行層疊。形成層疊上下文的方法有:

  • 根元素 <html></html>
  • position值為 absolute|relative,且 z-index值不為 auto
  • position 值為 fixed|sticky
  • z-index 值不為 auto 的flex元素,即:父元素 display:flex|inline-flex
  • opacity 屬性值小於 1 的元素
  • transform 屬性值不為 none的元素
  • mix-blend-mode 屬性值不為 normal 的元素
  • filterperspectiveclip-pathmaskmask-imagemask-bordermotion-path 值不為none 的元素
  • perspective 值不為 none 的元素
  • isolation 屬性被設置為 isolate 的元素
  • will-change 中指定了任意 CSS 屬性,即便你沒有直接指定這些屬性的值
  • -webkit-overflow-scrolling 屬性被設置 touch的元素

總結:

  1. 層疊上下文可以包含在其他層疊上下文中,並且一起組建了一個有層級的層疊上下文
  2. 每個層疊上下文完全獨立於它的兄弟元素,當處理層疊時只考慮子元素,這里類似於BFC
  3. 每個層疊上下文是自包含的:當元素的內容發生層疊后,整個該元素將會在父級疊上下文中按順序進行層疊

2. 層疊等級 (Stacking Level)

層疊等級 (層疊水平, Stacking Level) 決定了同一個層疊上下文中元素在z軸上的顯示順序的概念

  • 普通元素的層疊等級優先由其所在的層疊上下文決定
  • 層疊等級的比較只有在同一個層疊上下文元素中才有意義
  • 在同一個層疊上下文中,層疊等級描述定義的是該層疊上下文中的元素在Z軸上的上下順序

注意,層疊等級並不一定由 z-index 決定,只有定位元素的層疊等級才由 z-index 決定,其他類型元素的層疊等級由層疊順序、他們在HTML中出現的順序、他們的父級以上元素的層疊等級一同決定,詳細的規則見下面層疊順序的介紹。

3. z-index

在 CSS 2.1 中, 所有的盒模型元素都處於三維坐標系中。 除了我們常用的橫坐標和縱坐標, 盒模型元素還可以沿着"z 軸"層疊擺放, 當他們相互覆蓋時, z 軸順序就變得十分重要。

z-index 只適用於定位的元素,對非定位元素無效,它可以被設置為正整數、負整數、0、auto,如果一個定位元素沒有設置 z-index,那么默認為auto;

元素的 z-index 值只在同一個層疊上下文中有意義。如果父級層疊上下文的層疊等級低於另一個層疊上下文的,那么它 z-index 設的再高也沒用。所以如果你遇到 z-index 值設了很大,但是不起作用的話,就去看看它的父級層疊上下文是否被其他層疊上下文蓋住了。

4. 層疊順序 (Stacking Order)

這里其實是涉及了所謂的層疊水平(stacking level),有一張圖可以很好的詮釋:

運用上圖的邏輯,上面的題目就迎刃而解,inline-blcok 的 stacking level 比之 float 要高,所以無論 DOM 的先后順序都堆疊在上面。

不過上面圖示的說法有一些不准確,按照 W3官方 的說法,准確的 7 層為:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

稍微翻譯一下:

  1. 形成堆疊上下文環境的元素的背景與邊框
  2. 擁有負 z-index 的子堆疊上下文元素 (負的越高越堆疊層級越低)
  3. 正常流式布局,非 inline-block,無 position 定位(static除外)的子元素
  4. 無 position 定位(static除外)的 float 浮動元素
  5. 正常流式布局, inline-block元素,無 position 定位(static除外)的子元素(包括 display:table 和 display:inline )
  6. 擁有 z-index:0 的子堆疊上下文元素
  7. 擁有正 z-index: 的子堆疊上下文元素(正的越低越堆疊層級越低)

所以我們的兩個 div 的比較是基於上面所列出來的 4 和 5 。5 的 stacking level 更高,所以疊得更高。

不過!不過!不過!重點來了,請注意,上面的比較是基於兩個 div 都沒有形成 堆疊上下文 這個為基礎的。下面我們修改一下題目,給兩個 div ,增加一個 opacity:

.container{ position:relative; background:#ddd; } .container > div{ width:200px; height:200px; opacity:0.9; // 注意這里,增加一個 opacity } .float{ float:left; background-color:deeppink; } .inline-block{ display:inline-block; background-color:yellowgreen; margin-left:-100px; }

Demo戳我

會看到,inline-block 的 div 不再一定疊在 float 的 div 之上,而是和 HTML 代碼中 DOM 的堆放順序有關,后添加的 div 會 疊在先添加的 div 之上。

這里的關鍵點在於,添加的 opacity:0.9 這個讓兩個 div 都生成了 stacking context(堆疊上下文) 的概念。此時,要對兩者進行層疊排列,就需要 z-index ,z-index 越高的層疊層級越高。

堆疊上下文是HTML元素的三維概念,這些HTML元素在一條假想的相對於面向(電腦屏幕的)視窗或者網頁的用戶的 z 軸上延伸,HTML 元素依據其自身屬性按照優先級順序占用層疊上下文的空間。

 

層疊順序 (層疊次序, 堆疊順序, Stacking Order) 描述的是元素在同一個層疊上下文中的順序規則,從層疊的底部開始,共有七種層疊順序,如圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM