關(guān)于z-index的問(wèn)題是很多程序員都不知道它是如何起作用的。說(shuō)起來(lái)不難,但是大部分人并沒(méi)有花時(shí)間去看規(guī)范,這往往會(huì)照成嚴(yán)重的后果。
你不信?那就一起來(lái)看看下面的問(wèn)題。
問(wèn)題
在下面的HTML我們寫(xiě)了3個(gè)<div>元素,然后每個(gè)<div>元素里面都有一個(gè)<span>元素,每個(gè)<span>元素都有個(gè)背景色,并且使用absolute定位,為了能更清楚地看到z-index的效果,我們寫(xiě)了一些其他的樣式。第一個(gè)<span>元素的z-index值為1,其他兩個(gè)沒(méi)有設(shè)置。
代碼如下:
<div> <span class="red">Red</span></div><div> <span class="green">Green</span></div><div> <span class="blue">Blue</span></div>.red, .green, .blue { position: absolute;}.red { background: red; z-index: 1;}.green { background: green;}.blue { background: blue;}
然后挑戰(zhàn)來(lái)了: 嘗試把紅色的<span>元素放到其他兩個(gè)元素后面,但是必須遵守下面的規(guī)則:
不能修改HTML的內(nèi)容
不能增加或修改任何元素的z-index屬性
不能增加或修改任何元素的position屬性
想挑戰(zhàn)一些的話,就點(diǎn)擊上面Codepen的Edit按鈕去嘗試一下吧。如果你不能做到,那就接著看下去。
解決方案
解決方案很簡(jiǎn)單,你只需要給紅色的<span>標(biāo)簽增加一個(gè)opacity小于1,像下面這樣:
div:first-child { opacity: .99;}
如果你覺(jué)得不可思議了,不相信透明度會(huì)影響疊加順序,那么恭喜你,即將學(xué)習(xí)新的技能,一開(kāi)始看到我也不信。
接下來(lái)讓我們來(lái)摸索一番。
堆疊順序
z-index看上去很簡(jiǎn)單,z-index值大的元素在z-index值小的元素前面,對(duì)吧?但其實(shí)這只是z-index的一部分用法。很多程序猿都覺(jué)得很簡(jiǎn)單,沒(méi)有花太多時(shí)間去認(rèn)真閱讀規(guī)則。
HTML中的每一元素都是在其他元素的前面或者后面。這是眾所周知的堆疊順序(Stacking Order),這條規(guī)則在w3c規(guī)范里面說(shuō)的很清楚,但我前面提到過(guò)了,大部分程序猿并不真正理解。
如果沒(méi)有涉及z-index和position屬性的話,那規(guī)則很簡(jiǎn)單,堆疊順序就是元素在HTML中出現(xiàn)的順序。(當(dāng)然如果你對(duì)行內(nèi)元素使用負(fù)margin的話,
可能情況會(huì)復(fù)雜一些。)
加上position屬性的話,就是所有定位了得元素在沒(méi)有被定位的元素前面。(一個(gè)元素被定位的意思這里指的是它有一個(gè)position屬性,但是不是static,而是relative,absolute等)
再加上z-index屬性,事情就變得有點(diǎn)詭異。首先z-index值越大,越靠前。但是z-index屬性只作用在被定位了的元素上。所以如果你在一個(gè)沒(méi)被定位的元素上使用z-index的話,是不會(huì)有效果的。還有就是z-index會(huì)創(chuàng)建一個(gè)堆疊的上下文(Stacking Contexts),我們可以理解為一個(gè)層。
堆疊上下文
同一個(gè)父元素下面的元素會(huì)受父元素的堆疊順序影響,所以堆疊上下文是我們理解z-index和堆疊順序的關(guān)鍵。(下面為了簡(jiǎn)化,我們稱(chēng)堆疊上下文為層。)
每一個(gè)層都有唯一的根節(jié)點(diǎn)。當(dāng)一個(gè)元素創(chuàng)建一個(gè)層,那么它的所有子元素都會(huì)受到父元素的堆疊順序影響。意味著如果一個(gè)元素位于一個(gè)最低位置的層,那你z-index設(shè)置得再大,它也不會(huì)出現(xiàn)在其它層元素的上面。
現(xiàn)在我們來(lái)說(shuō)說(shuō)什么情況下會(huì)產(chǎn)生新的層:
當(dāng)一個(gè)元素位于HTML文檔的最外層(<html>元素)
當(dāng)一個(gè)元素被定位了并且擁有一個(gè)z-index值(不為auto)
當(dāng)一個(gè)元素被設(shè)置了opacity,transforms, filters, css-regions, paged media等屬性。
一二條規(guī)則,Web開(kāi)發(fā)者都知道,雖然他們不一定知道怎么描述
最后一條,是很多非w3c規(guī)范里面的文章很少提到的。通常來(lái)講,如果一個(gè)CSS屬性需要做一些特效的話,它都會(huì)創(chuàng)建一個(gè)新的層。
影響堆疊順序的因素有很多,我推薦你去看w3c規(guī)范,這篇文章我們主要探討關(guān)于層的內(nèi)容。
同一層里面的堆疊順序
下面是同一層里面的堆疊順序(從后到前):
層的根元素
被定位了得元素并且z-index值為負(fù),相同z-index的情況下,按照HTML元素的書(shū)寫(xiě)順序排列,下面相同。
沒(méi)有被定位的元素
被定位的元素,并且z-index值為auto
被定位了的元素并且z-index值為正。
注意:z-index值為負(fù)的元素比較特殊,他們會(huì)先被繪制,意味著他們可以出現(xiàn)在其他元素的后面,甚至出現(xiàn)在它的父元素后面。但是必要條件是該元素必須與父元素處于同一層,并且父元素不是這個(gè)層的根元素。
一個(gè)很好的例子 理解了如何和什么時(shí)候會(huì)產(chǎn)生一個(gè)新的層,那么下次如果你遇到z-index值設(shè)了很大,但是不起作用的話就去看看它的祖先是否產(chǎn)生了一個(gè)新的層。
總結(jié)
說(shuō)了這么多,我們來(lái)給之前的代碼加上堆疊順序。
<div><!-- 1 --> <span class="red"><!-- 6 --></span></div><div><!-- 2 --> <span class="green"><!-- 4 --><span></div><div><!-- 3 --> <span class="blue"><!-- 5 --></span></div>
當(dāng)我們?cè)O(shè)置了opacity之后變成下面這樣。
<div><!-- 1 --> <span class="red"><!-- 1.1 --></span></div><div><!-- 2 --> <span class="green"><!-- 4 --><span></div><div><!-- 3 --> <span class="blue"><!-- 5 --></span></div>
紅色的<span>從6變成1.1,我用'.'來(lái)標(biāo)記它是新生成的層里面的第一個(gè)元素。
最后我們來(lái)總結(jié)一下為什么紅色的<span>會(huì)去到下面:一開(kāi)始有兩個(gè)層,一個(gè)由根節(jié)點(diǎn)產(chǎn)生,一個(gè)由設(shè)置了z-index:1并且position:absolute的紅色<span>產(chǎn)生。當(dāng)我們?cè)O(shè)置了opacity時(shí),產(chǎn)生了第三個(gè)層,并且第三個(gè)層把紅色<span>產(chǎn)生的層包裹了,意味著剛開(kāi)始的z-index的作用域只在第三個(gè)層里面。而所有的<div>都沒(méi)有定位或者z-index,所以他們的堆疊順序按照HTML出現(xiàn)順序排列,于是第三個(gè)層就去到下面。
推薦閱讀
Elaborate description of Stacking Contexts The stacking context The Z-Index CSS Property: A Comprehensive Look 本文根據(jù)
@Philip Walton的《
What No One Told You About Z-Index》所譯,整個(gè)譯文帶有我們自己的理解與思想,如果譯得不好或有不對(duì)之處還請(qǐng)同行朋友指點(diǎn)。如需轉(zhuǎn)載此譯文,需注明英文出處:
http://philipwalton.com/articles/what-no-one-told-you-about-z-index/。
HelKyle
我是周曉楷,華南師范大學(xué)在校本科生,有輕微強(qiáng)迫癥,拖延癥,正在努力學(xué)習(xí)前端知識(shí)!微博@Helkyle。
如需轉(zhuǎn)載,煩請(qǐng)注明出處:http://www.w3cplus.com/css/what-no-one-told-you-about-z-index.html