深刻理解CSS中的層疊上下文和層疊順序

深刻理解CSS中的層疊上下文和層疊順序

上下文css

前端大全 · 2016-01-20 20:12html

深刻理解CSS中的層疊上下文和層疊順序

(點擊上方,可快速關注)前端


做者:張鑫旭
web

網址:http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/瀏覽器

零、世間的道理都是想通的wordpress


在這個世界上,凡事都有個前後順序,凡物都有個論資排輩。比方說食堂排隊打飯,對吧,講求先到先得,總不可能蜂擁而上。再好比說話語權,老婆的話永遠是對的,領導的話永遠是對的。佈局


在CSS屆,也是如此。只是,通常狀況下,你們歌舞昇平,看不出什麼差別,即所謂的衆平生等。可是,當發生衝突發生糾葛的時候,顯然,是不可能作到徹底等同的,前後順序,身份差別就顯現出來了。例如,傑克和羅斯,只能一人浮在木板上,此時,出現了衝突,結果你們都知道的。那對於CSS世界中的元素而言,所謂的「衝突」指什麼呢,其中,很重要的一個層面就是「層疊顯示衝突」。測試


默認狀況下,網頁內容是沒有偏移角的垂直視覺呈現,當內容發生層疊的時候,必定會有一個先後的層疊順序產生,有點相似於真實世界中論資排輩的感受。flex


而要理解網頁中元素是如何「論資排輩」的,就須要深刻理解CSS中的層疊上下文和層疊順序。spa


咱們你們可能都熟悉CSS中的z-index屬性,須要跟你們講的是,z-index實際上只是CSS層疊上下文和層疊順序中的一葉小舟。


1、什麼是層疊上下文


層疊上下文,英文稱做」stacking context」. 是HTML中的一個三維的概念。若是一個元素含有層疊上下文,咱們能夠理解爲這個元素在z軸上就「高人一等」。


這裏出現了一個名詞-z軸,指的是什麼呢?


表示的是用戶與屏幕的這條看不見的垂直線(參見下圖示意-紅線):



層疊上下文是一個概念,跟「塊狀格式化上下文(BFC)」相似。然而,概念這個東西是比較虛比較抽象的,要想輕鬆理解,咱們須要將其具象化。


怎麼個具象化法呢?


你能夠把「層疊上下文」理解爲當官:網頁中有不少不少的元素,咱們能夠當作是真實世界的芸芸衆生。真實世界裏,咱們大多數人是普通老百姓們,還有一部分人是作官的官員。OK,這裏的「官員」就能夠理解爲網頁中的層疊上下文元素。


換句話說,頁面中的元素有了層疊上下文,就比如咱們普通老百姓當了官,一旦當了官,相比普通老百姓而言,離皇帝更近了,對不對,就等同於網頁中元素級別更高,離咱們用戶更近了。


2、什麼是層疊水平


再來講說層疊水平。「層疊水平」英文稱做」stacking level」,決定了同一個層疊上下文中元素在z軸上的顯示順序。level這個詞很容易讓咱們聯想到咱們真正世界中的三六九等、論資排輩。真實世界中,每一個人都是獨立的個體,包括同卵雙胞胎,有差別就有區分。例如,雙胞胎雖然長得像Ctrl+C/Ctrl+V獲得的,但實際上,出生時間仍是有前後順序的,先出生的那個就大,大哥或大姐。網頁中的元素也是如此,頁面中的每一個元素都是獨立的個體,他們必定是會有一個相似的排名排序的狀況存在。而這個排名排序、論資排輩就是咱們這裏所說的「層疊水平」。層疊上下文元素的層疊水平能夠理解爲官員的職級,1品2品,縣長省長之類;對於普通元素,這個嘛……你本身隨意理解。


因而,顯而易見,全部的元素都有層疊水平,包括層疊上下文元素,層疊上下文元素的層疊水平能夠理解爲官員的職級,1品2品,縣長省長之類。而後,對於普通元素的層疊水平,咱們的探討僅僅侷限在當前層疊上下文元素中。爲何呢?由於不然沒有意義。


這麼理解吧~ 上面提過元素具備層疊上下文比如當官,你們都知道的,這當官的家裏都有丫環啊保鏢啊管家啊什麼的。所謂打狗看主人,A官員家裏的管家和B官員家裏的管家作PK其實是沒有意義的,由於他們牛不牛逼徹底由他們的主子決定的。一人得道雞犬升天,你說這和珅家裏的管家和七俠鎮婁知縣縣令家裏的管家有可比性嗎?李總理的祕書是否是分分鐘滅了你村支部書記的祕書(若是有)。


翻譯成術語就是:普通元素的層疊水平優先由層疊上下文決定,所以,層疊水平的比較只有在當前層疊上下文元素中才有意義。


須要注意的是,諸位千萬不要把層疊水平和CSS的z-index屬性混爲一談。沒錯,某些狀況下z-index確實能夠影響層疊水平,可是,只限於定位元素以及flex盒子的孩子元素;而層疊水平全部的元素都存在。


3、什麼是層疊順序


再來講說層疊順序。「層疊順序」英文稱做」stacking order」. 表示元素髮生層疊時候有着特定的垂直顯示順序,注意,這裏跟上面兩個不同,上面的層疊上下文和層疊水平是概念,而這裏的層疊順序是規則。


在CSS2.1的年代,在CSS3尚未出現的時候(注意這裏的前提),層疊順序規則遵循下面這張圖:



有人可能有見過相似圖,那個圖是不少不少年前老外繪製的,英文內容。而是更關鍵的是國內估計沒有同行進行過驗證與實踐,實際上不少關鍵信息缺失。上面是我本身手動重繪的中文版同時補充不少其餘地方絕對沒有的重要知識信息。若是想要無水印高清大圖,點擊這裏購買(0.5元)。


缺失的關鍵信息包括:


  1. 位於最低水平的border/background指的是層疊上下文元素的邊框和背景色。每個層疊順序規則適用於一個完整的層疊上下文元素。

  2. 原圖沒有呈現inline-block的層疊順序,實際上,inline-block和inline水平元素是同等level級別。

  3. z-index:0實際上和z-index:auto單純從層疊水平上看,是能夠當作是同樣的。注意這裏的措辭——「單純從層疊水平上看」,實際上,二者在層疊上下文領域有着根本性的差別。


下面我要向你們發問了,你們有沒有想過,爲何內聯元素的層疊順序要比浮動元素和塊狀元素都高?


爲何呢?我明明感受浮動元素和塊狀元素要更屌一點啊。


嘿嘿嘿,我就不賣關子了,直接看下圖的標註說明:



諸如border/background通常爲裝飾屬性,而浮動和塊狀元素通常用做佈局,而內聯元素都是內容。網頁中最重要的是什麼?固然是內容了哈,對不對!


所以,必定要讓內容的層疊順序至關高,當發生層疊是很好,重要的文字啊圖片內容能夠優先暴露在屏幕上。例如,文字和浮動圖片重疊的時候:



上面說的這些層疊順序規則仍是老時代的,若是把CSS3也牽扯進來,科科,事情就不同了。


4、務必牢記的層疊準則


下面這兩個是層疊領域的黃金準則。當元素髮生層疊的時候,其覆蓋關係遵循下面2個準則:


  1. 誰大誰上:當具備明顯的層疊水平標示的時候,如識別的z-indx值,在同一個層疊上下文領域,層疊水平值大的那一個覆蓋小的那一個。通俗講就是官大的壓死官小的。

  2. 後來居上:當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處於後面的元素會覆蓋前面的元素。


在CSS和HTML領域,只要元素髮生了重疊,都離不開上面這兩個黃金準則。由於後面會有多個實例說明,這裏就到此爲止。


5、層疊上下文的特性


層疊上下文元素有以下特性:


  • 層疊上下文的層疊水平要比普通元素高(緣由後面會說明);

  • 層疊上下文能夠阻斷元素的混合模式(見此文第二部分說明);

  • 層疊上下文能夠嵌套,內部層疊上下文及其全部子元素均受制於外部的層疊上下文。

  • 每一個層疊上下文和兄弟元素獨立,也就是當進行層疊變化或渲染的時候,只須要考慮後代元素。

  • 每一個層疊上下文是自成體系的,當元素髮生層疊的時候,整個元素被認爲是在父層疊上下文的層疊順序中。


翻譯成真實世界語言就是:


  • 當官的比老百姓更有機會面見聖上;

  • 領導下去考察,會被當地官員阻隔只看到繁榮看不到真實民情;

  • 一個家裏,爸爸能夠當官,孩子也是能夠同時當官的。可是,孩子這個官要受爸爸控制。

  • 本身當官,兄弟不佔光。有什麼福利或者變故只會影響本身的孩子們。

  • 每一個當官的都有屬於本身的小團體,當家屬管家發生摩擦磕碰的時候(包括和其餘官員的家屬管家),都是要優先看當官的也就是主子的臉色。


6、層疊上下文的建立


賣了這麼多文字,到底層疊上下文是個什麼鬼,卻是拿出來瞅瞅啊!


哈哈。如同塊狀格式化上下文,層疊上下文也基本上是有一些特定的CSS屬性建立的。我將其總結爲3個流派,也就是作官的3種途徑:


  1. 皇親國戚派:頁面根元素天生具備層疊上下文,稱之爲「根層疊上下文」。

  2. 科考入選派:z-index值爲數值的定位元素的傳統層疊上下文。

  3. 其餘當官途徑:其餘CSS3屬性。


//zxx: 下面不少例子是實時CSS效果,建議您去原地址瀏覽,以便預覽更準確的效果。


①. 根層疊上下文


指的是頁面根元素,也就是滾動條的默認的始做俑者<html>元素。這就是爲何,絕對定位元素在left/top等值定位的時候,若是沒有其餘定位元素限制,會相對瀏覽器窗口定位的緣由。


②. 定位元素與傳統層疊上下文


對於包含有position:relative/position:absolute的定位元素,以及FireFox/IE瀏覽器(不包括Chrome等webkit內核瀏覽器)(目前,也就是2016年初是這樣)下含有position:fixed聲明的定位元素,當其z-index值不是auto的時候,會建立層疊上下文。


知道了這一點,有些現象就好理解了。


以下HTML代碼:


<div style="position:relative; z-index:auto;">

<img src="mm1.jpg" style="position:absolute; z-index:2;"> <-- 橫妹子 -->

</div>

<div style="position:relative; z-index:auto;">

<img src="mm2.jpg" style="position:relative; z-index:1;"> <-- 豎妹子 -->

</div>



你們會發現,豎着的妹子(mm2)被橫着的妹子(mm1)給覆蓋了。


下面,咱們對父級簡單調整下,把z-index:auto改爲層疊水平一致的z-index:0, 代碼以下:


<div style="position:relative; z-index:0;">

<img src="mm1.jpg" style="position:absolute; z-index:2;"> <-- 橫妹子 -->

</div>

<div style="position:relative; z-index:0;">

<img src="mm2.jpg" style="position:relative; z-index:1;"> <-- 豎妹子 -->

</div>



你們會發現,尼瑪反過來了,豎着的妹子(mm2)這回趴在了橫着的妹子(mm1)身上。



爲何小小的改變會有想法的結果呢?



差異就在於,z-index:0所在的<div>元素是層疊上下文元素,而z-index:auto所在的<div>元素是一個普通的元素,因而,裏面的兩個<img>妹子的層疊比較就不受父級的影響,二者直接套用層疊黃金準則,這裏,二者有着明顯不一的z-index值,所以,遵循「誰大誰上」的準則,因而,z-index爲2的那個橫妹子,就趴在了z-index爲1的豎妹子身上。


而z-index一旦變成數值,哪怕是0,都會建立一個層疊上下文。此時,層疊規則就發生了變化。層疊上下文的特性裏面最後一條——自成體系。兩個<img>妹子的層疊順序比較變成了優先比較其父級層疊上下文元素的層疊順序。這裏,因爲二者都是z-index:0,層疊順序這一塊二者同樣大,此時,遵循層疊黃金準則的另一個準則「後來居上」,根據在DOM流中的位置決定誰在上面,因而,位於後面的豎着的妹子就天然而然趴在了橫着的妹子身上。對,沒錯,<img>元素上的z-index打醬油了!


有時候,咱們在網頁重構的時候,會發現,z-index嵌套錯亂,看看是否是受父級的層疊上下文元素干擾了。而後,可能沒多大意義了,但我仍是提一下,算是祭奠下,IE6/IE7瀏覽器有個bug,就是z-index:auto的定位元素也會建立層疊上下文。這就是爲何在過去,IE6/IE7的z-index會搞死人的緣由。


而後,我再提一下position:fixed, 在過去,position:fixed和relative/absolute在層疊上下文這一塊是一路貨色,都是須要z-index爲數值才行。可是,不知道何時起,Chrome等webkit內核瀏覽器,position:fixed元素自然層疊上下文元素,無需z-index爲數值。根據個人測試,目前,IE以及FireFox還是老套路。


③. CSS3與新時代的層疊上下文

CSS3的出現除了帶來了新屬性,同時還對過去的不少規則發出了挑戰。例如,CSS3 transform對overflow隱藏對position:fixed定位的影響等。而這裏,層疊上下文這一塊的影響要更加普遍與顯著。


以下:


  1. z-index值不爲auto的flex項(父元素display:flex|inline-flex).

  2. 元素的opacity值不是1.

  3. 元素的transform值不是none.

  4. 元素mix-blend-mode值不是normal.

  5. 元素的filter值不是none.

  6. 元素的isolation值是isolate.

  7. will-change指定的屬性值爲上面任意一個。

  8. 元素的-webkit-overflow-scrolling設爲touch.


基本上每一項都有不少槽點。


  1. display:flex|inline-flex與層疊上下文


注意,這裏的規則有些負責。要知足兩個條件才能造成層疊上下文:條件1是父級須要是display:flex或者display:inline-flex水平,條件2是子元素的z-index不是auto,必須是數值。此時,這個子元素爲層疊上下文元素,沒錯,注意了,是子元素,不是flex父級元素。


眼見爲實,給你們上例子吧。


以下HTML和CSS代碼:


<div class="box">

<div>

<img src="mm1.jpg">

</div>

</div>


.box { }

.box > div { background-colorblue; z-index1; } /* 此時該div是普通元素,z-index無效 */

.box > div > img {

positionrelative; z-index: -1; right: -150px; /* 注意這裏是負值z-index */

}


結果以下:



會發現,妹子跑到藍色背景的下面了。爲何呢?層疊順序圖能夠找到答案,以下:



從上圖能夠看出負值z-index的層疊順序在block水平元素的下面,而藍色背景div元素是個普通元素,所以,妹子直接穿越過去,在藍色背景後面的顯示了。


如今,咱們CSS微調下,增長display:flex, 以下:


.box { displayflex; }

.box > div { background-colorblue; z-index

相關文章
相關標籤/搜索