在有些 CSS 相互影響做用下,對元素設置的 z-index
並不會按實際大小疊加,一直不明白其中的原理,最近特地查了一下相關資料,作一個小總結。css
層疊上下文(stacking content)是 HTML 中的三維概念,也就是元素z軸。層疊順序(stacking order)表示層疊時有着特定的垂直顯示順序。html
當具備明顯的層疊水平標示的時候,如識別的 z-indx
值,在同一個層疊上下文領域,層疊水平值大的那一個覆蓋小的那一個。web
當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處於後面的元素會覆蓋前面的元素。瀏覽器
層疊上下文有如下特性:app
對於包含 position: relative;
position: absolute;
的定位元素,以及 FireFox/IE瀏覽器下包含 position
聲明定位的元素,當其 z-index
值不是 auto
的時候,會建立層疊上下文。flex
HTML 代碼url
<div class="red-wrapper"> <div class="red">小紅</div> </div> <div class="gray-wrapper"> <div class="gray">小灰</div> </div>
CSS代碼spa
.red-wrapper { position: relative; z-index: auto; } .red { position: absolute; z-index: 2; width: 300px; height: 200px; text-align: center; background-color: brown; } .gray-wrapper { position: relative; z-index: auto; } .gray { position: relative; z-index: 1; width: 200px; height: 300px; text-align: center; background-color: gray; }
當兩個兄弟元素 z-index
都爲 auto
時,它們爲普通元素,子元素遵循」誰大誰上「的原則,因此小灰 z-index: 1;
輸給了小紅的 z-index: 2;
,被壓在了下面code
然而當 z-index
變成數值時,就會建立一個層疊上下文,各個層疊元素相互獨立,子元素受制於父元素的層疊順序。將兄弟元素的 z-index
從 auto
變成了數值 0
,他們的子元素的之間的層疊關係就不不受自己 z-index
的影響,而是由父級元素的 z-index
決定。orm
下面小紅和小灰的父級的 z-index
都調整成 0
.red-wrapper { /* 其餘樣式 */ z-index: 0; } .gray-wrapper { /* 其餘樣式 */ z-index: 0; }
就會發現小灰在小紅的上面了,由於小灰的父級和小紅的父級都變成了層疊上下文元素,層疊級別同樣,根據文檔流中元素位置」後來居上「原則。
父級是display: flex
或者display: inline-flex;
,子元素的z-index
不是auto
,此時,這個子元素(注意這裏是子元素)爲層疊上下文元素。
HTML 代碼
<div class="wrapper"> <div class="gray"> 小灰 <div class="red">小紅</div> </div> </div>
CSS代碼
.wrapper { display: flex; } .gray { z-index: 1; width: 200px; height: 300px; text-align: center; background-color: gray; } .red { z-index: -1; width: 300px; height: 200px; text-align: center; background-color: brown; position: relative; }
這樣,因爲小灰的父級的 display: flex;
,自身的 z-index
不爲 auto
,所以變成了層疊上下文元素,本來小紅墊底變成了小灰墊底了。
具備
mix-blend-mode
屬性的元素是層疊上下文元素
CSS 屬性mix-blend-mode
(混合模式),能夠將疊加的元素的內容和背景混合在一塊兒。
代碼同上,只需在小灰上添加 mix-blend-mode
屬性,爲了能查看到混合效果,將外面容器增長一個背景圖。
.wrapper { background-image: url("./jz.png"); } .gray { /* 其餘樣式 */ mix-blend-mode: darken; }
同理,小灰有 mix-blend-mode
屬性,變成了層疊上下文元素,讓小灰墊底。
若是元素的
opacity
不爲1,這個元素爲層疊上下文元素
HTML 代碼
<div class="gray"> 小灰 <div class="red">小紅</div> </div>
CSS代碼
.gray { z-index: 1; width: 200px; height: 300px; text-align: center; background-color: gray; opacity: 0.5; } .red { z-index: -1; width: 300px; height: 200px; text-align: center; background-color: brown; position: relative; }
因爲小灰自身有 opacity
半透明屬性,變成了層疊上下文元素,使得小紅 z-index: -1;
也沒法穿透。
應用了
transform
的元素爲層疊上下文元素
代碼同上,只不過把小灰應用 transform
變換。
.gray { /* 其餘相關樣式 */ transform: rotate(30deg); }
同理,小灰應用 transform
變換,變成了層疊上下文元素,使得小紅 z-index: -1;
也沒法穿透。
具備
filter
屬性的元素是層疊上下文元素
代碼同上,只不過把小灰加上 filter
屬性。
.gray { /* 其餘相關樣式 */ filter: blur(5px);; }
同理,小灰有 filter
屬性,變成了層疊上下文元素,使得小紅 z-index: -1;
仍是在小灰上層。
具備
will-change
屬性的元素是層疊上下文元素
代碼同上,只不過把小灰加上 will-change
屬性。
.gray { /* 其餘相關樣式 */ filter: will-change;; }
結果,同理如上。
綜合來看元素層疊規則,首先要理解在什麼狀況下元素是層疊上下文元素
position: relative|absolute|fixed;
,且 z-index
不爲 auto
(webkit
內核瀏覽器,fixed
定位無此限制)的元素是層疊上下文元素;display: flex|inline-flex;
子元素的 z-index
不是 auto
,此時,這個子元素(注意這裏是子元素)爲層疊上下文元素mix-blend-mode
屬性的元素opacity
屬性不爲1的元素transform
變換的元素filter
屬性的元素will-change
屬性的元素其次要理解疊層準則:」誰大誰上「,」後來居上「,最後就是要了解層疊上下文主要特性(詳見文章層疊上下文的特性)。完~