一、背景
你有沒有在項(xiàng)目代碼中遇到這樣一種情況,由于代碼是小組協(xié)同開發(fā),每個(gè)人所寫的部分都不一樣,但是會(huì)組合到一起。而每個(gè)人的CSS中的樣式也是肯定不一樣的,那么對于定位元素,層疊順序可能會(huì)影響一個(gè)組件在頁面中的顯示情況。于是大家都會(huì)設(shè)定z-index來使自己寫的小組件一定是在某種情況下可展示的,但是自己無論怎樣調(diào)整z-index的值都無法達(dá)到效果。也就是說,雖然我們把當(dāng)前的某一個(gè)元素的z-index設(shè)為了9999999...,但還是無法達(dá)到我們的效果,那么我們就進(jìn)入了一個(gè)誤區(qū)。
比如以下demo:
.stacking-context1 {
height: 200px;
width: 100%;
background-color: green;
position: absolute;
z-index: 1;
}
.stacking-context2 {
height: 100px;
width: 100%;
background-color: blue;
position: absolute;
z-index: 999;
}
.stacking-context3 {
height: 200px;
width: 100%;
background-color: pink;
position: absolute;
z-index: 2;
}
<div class="stacking-context1">
z-index: 1
<div class="stacking-context2">z-index: 999</div>
</div>
<div class="stacking-context3">z-index: 2</div>
按照我們的預(yù)想,現(xiàn)在的堆疊順序應(yīng)該為:

實(shí)際為:

那為何會(huì)出現(xiàn)這種情況呢?
二、探討
當(dāng)我們有一個(gè) <div id="parent"> 包著一群 <div class="child"> 元素時(shí),它們的堆疊順序通常會(huì)一起被移動(dòng)(從父原則),這整個(gè)群組的順序就是 stacking context,要完全理解 stacking context 我們就必須要參透 z-index 是怎麼排序 stacking order。
每一個(gè) stacking context 有一個(gè)唯一的 HTML 元素當(dāng)作其根元素,當(dāng)一個(gè)新的 stacking context 或者我們翻作堆疊環(huán)境被建立在一個(gè)元素上時(shí),這個(gè)堆疊環(huán)境就會(huì)控管它內(nèi)部的子元素的順序 stacking order,意思是如果其中一個(gè)元素在這個(gè)堆疊環(huán)境中順序被排在最底下,那它就完全沒機(jī)會(huì)出現(xiàn)在另外一個(gè)元素排位較高的堆疊環(huán)境前面,就算他的 z-index 設(shè)成 9999999。
從另外一個(gè)角度來說,每一個(gè)被設(shè)定 position 的元素除了自己的 stacking order 另外如果內(nèi)部還有子元素,就會(huì)有一個(gè) stacking context 來管制底下的元素。
要建立一個(gè)堆疊環(huán)境 stacking context有下面三者方式,只要使用其一即可:
1.當(dāng)元素是網(wǎng)頁文件的根元素通常就是 <html>
2.當(dāng)元素被設(shè)定 position 除了 static 以外的值,然後 z-index 設(shè)定為除了 auto 以外的值
3.當(dāng)元素設(shè)定了 opacity 且值小於 1
上面提到的三種方式中,前兩者大部分的開發(fā)者都知道,即使他們不懂原理但還是會(huì)使用。第三種方式除了 w3c 規(guī)範(fàn),大多開發(fā)者都不曾提到。
此外除了 opacity 另外一些新的屬性像是 transforms, filters, css-regions, paged media 等等都會(huì)產(chǎn)生 stacking context。
還有當(dāng) css 屬性需要在超出螢?zāi)坏牡胤戒秩荆矔?huì)產(chǎn)生一個(gè) stacking context。
來源:https://andyyou.github.io/2016/03/03/z-index/
如何決定元素在堆疊環(huán)境中的位置?
在單一的堆疊環(huán)境從最下面(后)到上面(前)規(guī)則如下
- 執(zhí)行堆疊的根元素。
- 有設(shè)定 position 且 z-index 為負(fù)數(shù)的元素和它們的子元素,-1 在 -2 前面。
- 沒有設(shè)定 position 的元素,一般元素。
- 有設(shè)定 position 且 z-index 為 auto,設(shè)定 opacity 小于 1 和其他 transforms 等屬性也在此列。
- 有設(shè)定 position 且 z-index 為正數(shù)。
都一樣的時(shí)候就比文件中代碼出現(xiàn)的先后順序,后出現(xiàn)的出現(xiàn)在上面。
因此,當(dāng)我們的某個(gè)元素已經(jīng)創(chuàng)建了“堆疊上下文環(huán)境”(stacking contetxt),那么它里面的元素再怎么設(shè)置z-index也不可能影響它的父元素所在的堆疊上下文環(huán)境中的順序,也就是說他只能在他的按順序已創(chuàng)建了堆疊上下文環(huán)境的元素中進(jìn)行比較,而他的父元素的堆疊順序決定了他在父元素所處環(huán)境中的位置。
也就是說當(dāng)我們把z-index設(shè)得很大卻無濟(jì)于事的時(shí)候,很可能該元素的上層元素已經(jīng)具備stacking context了。
所以,為了達(dá)到我們在demo中想要的效果其實(shí)很簡單,只要把stacking-context1的z-index改為3就行了。
.stacking-context1 {
height: 200px;
width: 100%;
background-color: green;
position: absolute;
z-index: 3;
}
.stacking-context2 {
height: 100px;
width: 100%;
background-color: blue;
position: absolute;
z-index: 999;
}
.stacking-context3 {
height: 200px;
width: 100%;
background-color: pink;
position: absolute;
z-index: 2;
}
<div class="stacking-context1">
z-index: 1
<div class="stacking-context2">z-index: 999</div>
</div>
<div class="stacking-context3">z-index: 2</div>