關于z-index的(de)真正問(wèn)題
關于z-index的(de)真正問(wèn)題是(shì),很(hěn)少(shǎo)有(yǒu)人(rén)∞理(lǐ)解它到(dào)底是(shì)怎麽用(yòng)。其實它并不(bù)複雜(zá),但(dàn)是(shì)如(rú)果你(nǐ)從(c"óng)來(lái)沒有(yǒu)花(huā)一(yī)定時(shí)間(jiān)去(qù)看(kàn)具體(tǐ)的(de)z-index 相(xiàng)關文(wén)檔,那(nà)麽你(nǐ)很(hěn)可(kě)能(néng)會(huì)忽略一(yī)些(xiē)重要(yào)的(de↔)信息。
不(bù)相(xiàng)信我嗎(ma)?好(hǎo)吧(ba),看(kàn)看(kàn)你(nǐ)能(néng)否解決下(xià)面這(zhè)個(gè)問(wèn)題:
問(wèn)題:
在接下(xià)來(lái)的(de)HTML裡(lǐ) 有(yǒu)三個(gè)<div>元®素,并且每個(gè)<div>裡(lǐ)包含一(yī)個(gè)<span>元素。每 個(gè)&•lt;span>被分(fēn)别給定一(yī)個(gè)背景顔色:紅(hóng)、綠(lǜ)、藍(£lán)。每個(gè)<span>被放(fàng)置到(dào)文(wén)檔的(de)左上(shàng)角附近(jΩìn),部分(fēn)重疊著(zhe)其他(tā) 的(de)<span>元素,這(zhè)樣你(nǐ)就(jiù)可(kě)以看(kàn)到(dào)哪些(x±iē)是(shì)被堆疊在前面。第一(yī)個(gè)<span>有(yǒu)一(yī)個(gè)z-index的( de)值為(wèi)1,而其他(tā)兩個(gè)沒有(yǒu)任 何z-index值。
以下(xià)就(jiù)是(shì)這(zhè)個(gè)HTML和(hé)它的(de)基本CSS。
HTML代碼
<div>
<span>Red</span>
</div>
<div>
<span>Green</span>
</div>
<div>
<span>Blue</span>
</div>
CSS代碼
.red, .green, .blue {
position: absolute;
}
.red {
background: red;
z-index: 1;
}
.green {
background: green;
}
.blue {
background: blue;
}
關于z-index的(de)那(nà)些(xiē)事(shì)兒(ér)
挑戰:
嘗試使紅(hóng)色<span>元素堆在藍(lán)色和(hé)綠(lǜ)色<span>的(de)後面,不(bσù)要(yào)打破以下(xià)規則:
不(bù)要(yào)以任何方式改變HTML标記
不(bù)要(yào)添加/修改任何元素的(de)z-index屬性
不(bù)要(yào)添加/修改任何元素的(de)position屬性
如(rú)果你(nǐ)找到(dào)了(le)答(dá)案,那(nà)麽它應該像下(xià)面這(zhè)樣:
<div>
<span>Red</span>
</div>
<div>
<span>Green</span>
</div>
<div>
<span>Blue</span>
</div>
div:first-child {
opacity: .99;
}
.red, .green, .blue {
position: absolute;
}
.red {
background: red;
z-index: 1;
}
.green {
background: green;
}
.blue {
background: blue;
}
關于z-index的(de)那(nà)些(xiē)事(shì)兒(ér)
解決方案:
這(zhè)個(gè)解決方法是(shì)在第一(yī)個(gè)<div>裡(lǐ)(紅(hóng)色<span>的(de)父節點)添加一(yī¥)個(gè)小(xiǎo)于1的(de)opacity屬性值。下(xià)面就(jiù)是(shì)被添加的(de)CSS的(de)例子(zǐ):
div:first-child {
opacity: .99;
}
如(rú)果你(nǐ)現(xiàn)在很(hěn)震驚,但(dàn)是(shì)仍然百思不(bù)得(de)其解,并且不(bù)相(xiàng)信opacity能(néng)決定哪個(gè)元素<堆在前面,歡迎來(lái)社區(qū)提問(wèn),當第一(yī)次在這(zhè)個(gè)問(wèn)題上(shàng)被困擾時(shí)我同樣很(hěnλ)震驚。
希望接下(xià)來(lái)的(de)內(nèi)容能(néng)夠讓你(nǐ)對(duì)這(zhè)個(gè)問(wèn)題更清楚些(xiē)。
堆棧順序
Z-index看(kàn)上(shàng)去(qù)如(rú)此簡單:高(gāo)的(de)z-index堆在低(dī)的(de)z-ind"ex的(de)前面,對(duì)嗎(ma)?這(zhè)實際上(shàng)是(shì)錯(cuò)的(de),是(shì)z-index問(wèn)題的(de)一(yī)部分(fē✔n)。它看(kàn)上(shàng)去(qù)如(rú)此的(de)簡單,以至于很(hěn)多(duō)開(kāi)發者沒有(yǒu)花(huā)相(xiàng)應的(de)時(♣shí)間(jiān)去(qù)讀(dú)相(xiàng)關的(de)規則。
每一(yī)個(gè)在HTML文(wén)檔中的(de)元素既可(kě)以在其他(tā)元素的(de)前面,也(yě)可(kě)以在其他(tā)元素的(d e)後面。這(zhè)就(jiù)是(shì)所謂的(de)堆棧順序。決定這(zhè)個(gè)順序的(de)規則被十分(fēn)清楚的(≥de)定義在說(shuō)明(míng)文(wén)檔中,但(dàn)是(shì)就(jiù)像之前我已經提到(dào)過,這(zhè)些(xiē)文(w$én)檔沒有(yǒu)被大(dà)多(duō)數(shù)開(kāi)發者們完全弄明(míng)白(bái)。
當z-index和(hé)position屬性不(bù)被包括在內(nèi)時(shí),這(zhè)些(xiē)規則相(xiàng)當簡單:基本上(shàng),堆棧順序和(hé)φ元素在HTML中出現(xiàn)的(de)順序一(yī)樣。(好(hǎo)吧(ba),其實是(shì)有(yǒu)一(yī)點複雜(zá)的(de),但(dàn)是(shì)隻要(♠yào)你(nǐ)不(bù)使用(yòng)壓縮邊界來(lái)重疊行(xíng)內(nèi)元素,你(nǐ)可(kě)能(néng)不(bù)會(huì)遇到(★dào)邊界問(wèn)題。)
當你(nǐ)把位置屬性也(yě)包括在內(nèi)介紹時(shí),任何定位元素(和(hé)他(tā)們的(de)子(zǐ)元素)都(dōu)在非定位元素✔前被顯示出來(lái)。(說(shuō)一(yī)個(gè)元素被“定位”意思是(shì)它有(yǒu)一(yī)個(gè)不(bù)同于靜(jìng)态的(d£e)位置值,例如(rú)相(xiàng)對(duì)的(de),絕對(duì)的(de),等等。)
最 後,當z-index被提及時(shí),事(shì)情變的(de)有(yǒu)點兒(ér)複雜(zá)。最初,很(hěn)自(zì)然的(de)假設帶有(yǒu)高(gāo)z-index•值的(de)元素會(huì)在帶有(yǒu)低(dī)z-index值的(de)元素前面,但(dàn)是(shì)後來(lái)發 現(xiàn)沒那(nà)麽簡單。首先,z->index隻對(duì)定位元素起作(zuò)用(yòng)。如(rú)果你(nǐ)嘗試對(duì)非定位元素設定一(yī)個(g<è)z-index值,那(nà)麽肯定不(bù)起作(zuò)用(yòng)。其次,z-index值能(néng) 創建堆棧上(shàng)下(xià)文(wén)環境,并且≤突然發現(xiàn)看(kàn)似簡單的(de)東(dōng)西(xī)變的(de)更加複雜(zá)了(le)。
堆棧上(shàng)下(xià)文(wén)
一(yī)組具有(yǒu)共同雙親的(de)元素,按照(zhào)堆棧順序一(yī)起向前或向後移動構成了(le)所謂的(de)堆棧上(shàng)下(xià)文(wén)。充分♥(fēn)理(lǐ)解堆棧上(shàng)下(xià)文(wén)是(shì)真正掌握z-index和(hé≥)堆棧順序工(gōng)作(zuò)原理(lǐ)的(de)關鍵。
每 一(yī)個(gè)堆棧上(shàng)下(xià)文(wén)都(dōu)有(yǒu)一(yī)個(gè)HTM≈L元素作(zuò)為(wèi)它的(de)根元素。當一(yī)個(gè)新的(de)堆棧上(shàng)下(xià)文(wén)在一(yī)個(gè)元素上(shàng)形成,那(nà)麽這(z£hè)個(gè)堆棧上(shàng)下(xià)文(wén)會(huì)限制(zhì)所有(yǒu)的(de)子(zǐ)元素以堆棧的(de)順序存儲在一(yī) 個(gè)特别的(de)地(dì≈)方。那(nà)意味著(zhe)一(yī)旦一(yī)個(gè)元素被包含在處于底部堆棧順序的(de)堆棧上(shàng)下(xià)®文(wén)中,那(nà)麽就(jiù)沒有(yǒu)辦法先出現(xiàn)于其他(tā)處于更高(gāo)的(de)ε堆棧順序的(de)不(bù)同堆棧上(shàng)下(xià)文(wén)元素,就(jiù)算(suàn) z-index值是(shì)十億也(yě)不(bù)行(xíng)!
現(xiàn)在,堆棧上(shàng)下(xià)文(wén)有(yǒu)三種方法可(kě)以在一(yī)個(gè)元素上(shàng)形成:
當一(yī)個(gè)元素是(shì)文(wén)檔的(de)根元素時(shí)(<html>元素)
當一(yī)個(gè)元素有(yǒu)一(yī)個(gè)position值而不(bù)是(shì)static,有(yǒu)一(yī)個(gè)z-indeΩx值而不(bù)是(shì)auto
當一(yī)個(gè)元素有(yǒu)一(yī)個(gè)opacity值小(xiǎo)于1
前兩種形成堆棧上(shàng)下(xià)文(wén)的(de)方法具有(yǒu)很(hěn)大(dà)意義并且被廣大(dà)Web開(kāi)發者∑所理(lǐ)解(即使他(tā)們不(bù)知(zhī)道(dào)這(zhè)些(xiē)被叫做(zu&ò)什(shén)麽)。第三種方法(opacity)幾乎從(cóng)來(lái)沒在w3c說(shuō)明(míng)文(wén)檔之外(wài)被提及過。
用(yòng)堆棧順序決定一(yī)個(gè)元素的(de)位置
實際上(shàng),為(wèi)一(yī)個(gè)頁面上(shàng)的(de)所有(yǒu)元素決定≈全局堆棧順序(包括邊界、背景、文(wén)本節點、等等)是(shì)極度複雜(zá)的(de),并且遠(yuǎn)遠(yuǎn)超越了(le)本文(wén)講述的(de)範圍(再一λ(yī)次,參考文(wén)檔)。但(dàn)是(shì)我們最大(dà)的(de)目的(de),就(jiù)是(shì)₩基本了(le)解這(zhè)個(gè)順序,它能(néng)夠在很(hěn)長(cháng)一(yī)φ段時(shí)間(jiān)內(nèi)幫助我們提高(gāo)CSS開(kāi)發的(de)可(kě)預測性。所以,讓我們打破順序,分(fēn)解為(wèi)獨立的(de)堆棧上(shà©ng)下(xià)文(wén)。
在同樣的(de)堆棧上(shàng)下(xià)文(wén)裡(lǐ)的(de)堆棧順序
下(xià)面是(shì)幾條基本的(de)規則,來(lái)決定在一(yī)個(gè)單獨的(de)堆☆棧上(shàng)下(xià)文(wén)裡(lǐ)的(de)堆棧順序(從(cóng)後向前):
堆棧上(shàng)下(xià)文(wén)的(de)根元素
定位元素(和(hé)他(tā)們的(de)子(zǐ)元素)帶著(zhe)負數(shù)的(de)z-index值(高(gāo)的(de)值被堆疊在低(dī)值的(de)前面∑;相(xiàng)同值的(de)元素按照(zhào)在HTML中出現(xiàn)的(de)順序堆疊)
非定位元素(按照(zhào)在HTML中出現(xiàn)的(de)順序排序)
定位元素(和(hé)他(tā)們的(de)子(zǐ)元素)帶著(zhe)auto的(de)z-index值(按照(zhào)÷在HTML中出現(xiàn)的(de)順序排序)
定位元素(和(hé)他(tā)們的(de)子(zǐ)元素)帶著(zhe)正z-index值(高(gāo)的(de☆)值被堆疊在低(dī)值的(de)前面;相(xiàng)同值的(de)元素按照(zhào)在HTML中出現(xiàn)的(de)順序堆疊)
注 解:定位元素帶有(yǒu)負的(de)z-index值被在一(yī)個(gè)堆棧上(shàng)下(xià)文(wén∏)中先排序,這(zhè)意味著(zhe)他(tā)們出現(xiàn)在所有(yǒu)其他(tā)元素的(de)後面。正因如(rú)此,它使一(yī)≤個(gè)元素出現(xiàn)在自(zì)己父元素之後 成為(wèi)可(kě)能(néng),這(zhè)以前通(tōng)常是(shì)不(bù₹)可(kě)能(néng)的(de)事(shì)。當然,這(zhè)局限于它的(de)父元素與它在同一(yī)個(gè)堆棧上(shàn€g)下(xià)文(wén),并且不(bù)是(shì)那(nà)個(gè)堆棧上(shàng)下(xià)文(wén)的(de)根元素。一(yī)個(gè)偉大(dà)的(de)例子(✔zǐ)如(rú)Nicolas Gallagher的(de)CSS不(bù)用(yòng)圖像降低(dī)陰影(βyǐng)。
全局堆棧順序
堅定的(de)理(lǐ)解了(le)為(wèi)什(shén)麽/什(shén)麽時(shí)候新的(de)堆棧上(♠shàng)下(xià)文(wén)形成,同時(shí)掌握了(le)同一(yī)個(gè)堆棧上(shàng)下(xià)文(wén)的(de)堆棧順序,現(xiàn)在讓你(nǐ)來(lái)₽找出一(yī)個(gè)特定元素将出現(xiàn)在全局堆棧裡(lǐ)的(de)順序不(bù)是(shì)那φ(nà)麽糟糕了(le)吧(ba)?
避免錯(cuò)誤的(de)關鍵是(shì)能(néng)夠發現(xiàn)新的(de)堆棧上(shàng)下(xià)文(♣wén)什(shén)麽時(shí)候形成。如(rú)果你(nǐ)對(duì)一(yī)個(gè)元素設置φ了(le)z-index值為(wèi)十億但(dàn)是(shì)它沒有(yǒu)在堆棧順序中向前移動,檢查一(yī)下(xià)它的(de)祖先♣樹(shù),看(kàn)是(shì)否它的(de)父節點形成了(le)堆棧上(shàng)下(xià)文(wén)。如(r★ú)果是(shì)那(nà)樣的(de)話(huà),你(nǐ)的(de)z-index值即使有(yǒu)十億也(yě)不(bù)會(huì)給你(nǐ)帶來(♦lái)好(hǎo)處。
包紮救治
回到(dào)之前的(de)原始問(wèn)題,我已經重建了(le)這(zhè)個(gè)HTML的(de)結構,添加了(le)一(yī)些(xiē)§注釋,每一(yī)個(gè)标簽指明(míng)了(le)它在堆棧裡(lǐ)的(de)順序。這(zhè)個(gè)順序是(shì)假設最初的(d¥e)CSS。
<div><!-- 1 -->
<span><!-- 6 --></span>
</div>
<div><!-- 2 -->
<span><!-- 4 --><span>
</div>
<div><!-- 3 -->
<span><!-- 5 --></span>
</div>
當我們添加opacity到(dào)第一(yī)個(gè)<div>,堆棧順序像下(xià)面這(zhè)樣改變:
<div><!-- 1 -->
<span><!-- 1.1 --></span>
</div>
<div><!-- 2 -->
<span><!-- 4 --><span>
</div>
<div><!-- 3 -->
<span><!-- 5 --></span>
</div>
span.red曾經的(de)順序是(shì)6,但(dàn)現(xiàn)在改為(wèi)1.1。我已經使用(yòng)“.”來(lái)↕标注一(yī)個(gè)新的(de)上(shàng)下(xià)文(wén)環境的(de)形成。sp±an.red現(xiàn)在是(shì)那(nà)個(gè)新的(de)上(shàng)下(xià)文(wén₽)的(de)第一(yī)個(gè)元素。
現(xiàn) 在似乎更清晰了(le),關于為(wèi)什(shén)麽紅(hóng)色盒子(zǐ)跑到(dào)其他(tā)盒子(zǐ)的(de)後面。原始的(de)例子(zǐ)隻包含±兩個(gè)堆棧上(shàng)下(xià)文(wén),根元素和(hé)形成span.red的(de)那(nà)個(gè)。當我們添加 opacity到(dào)span.red的(→de)父節點上(shàng),形成了(le)第三個(gè)堆棧上(shàng)下(xià)文(wén),結果顯示在span.red上(shàng)的(de)αz-index值隻能(néng)應用(yòng)在那(nà)個(gè)新的(de)堆棧上(shàng)下(xià)文(wén) 中。因為(wèi)第一(yī)個↑(gè)<div>(應用(yòng)opacity的(de)那(nà)個(gè))和(hé)它的(de)兄弟(dì)元素沒有(yǒu)position或者z-index♣值的(de)集合,他(tā)們的(de)堆棧順序是(shì)由 他(tā)們在HTML裡(lǐ)的(de)源順序決定的(de),也(yě)就(ji®ù)是(shì)說(shuō)第一(yī)個(gè)<div>,和(hé)它的(de)堆棧上(shàng)∏下(xià)文(wén)裡(lǐ)的(de)所有(yǒu)元素被第二個(gè)和(hé)第三個(gè)<div>元素分(fēn)離(lí)。
