CSS z-index 属性的使用方法和層級概念

11699847034_6b43d779b8_z

CSS中的z-index屬性用於設置節點的堆疊順序.但同時,我們總是對堆疊順序捉摸不透,將z-index的值設得很大也未必能將節點顯示在最前面!今天Designrock分享一篇用一些例子對z-index的使用方法進行分析,並且為各位帶入z -index 層級樹的概念

文章來源:http://www.neoease.com/css-z-index-property-and-layering-tree/

順序規則

如果不對節點設定position 屬性, 位於文檔流後面的節點會遮蓋前面的節點.

< div  id = "a" > A < / div > 
< div  id = "b" > B < / div >

CSS z-index 屬性順序規則的例子


定位規則

如果將position設為static,位於文檔流後面的節點依然會遮蓋前面的節點浮動,所以position:static不會影響節點的遮蓋關係.

< div  id = "a"  style = "position:static;" > A < / div > 
< div  id = "b" > B < / div >

CSS z-index 屬性定位規則的例子, static

如果將position 設為relative (相對定位), absolute (絕對定位) 或者fixed (固定定位), 這樣的節點會覆蓋沒有設置position 屬性或者屬性值為static 的節點, 說明前者比後者的默認層級高.

< div  id = "a"  style = "position:relative;" > A < / div > 
< div  id = "b" > B < / div >

CSS z-index 屬性定位規則的例子, relative | absolute | fixed

在沒有z-index屬性干擾的情況下,根據這順序規則和定位規則,我們可以做出更加複雜的結構.這裡我們對A和B都不設定position,但對A的子節點A-1設定position:relative .根據順序規則, B會覆蓋A,又根據定位規則A’會覆蓋B.

< div  id = "a" > 
	< div  id = "a-1"  style = "position:relative;" > A-1 < / div > 
< / div > 
< div  id = "b" > B < / div >

CSS z-index 屬性互相覆蓋的例子

上面互相覆蓋在什麼時候用到這樣的實現? 看起來偏門, 其實很常用, 比如說, 電子商務網站側欄的類目展示列表就可以用這個技巧來實現.

下圖是某網站的類目展示區域, 二級類目的懸浮層覆蓋一級類目列表外框, 而一級類目的節點覆蓋二級類目的懸浮層. 如果使用CSS 實現展示效果,一級類目的外框相當於上面例子中的A, 一級類目的節點相當於A-1, 二級類目的懸浮層相當於B.

電子商務網站側欄的類目展示列表

參與規則

我們嘗試不用position 屬性, 但為節點加上z-index 屬性.​​ 發現z-index 對節點沒起作用.

< div  id = "a"  style = "z-index:2;" > A < / div > 
< div  id = "b"  style = "z-index:1;" > B < / div > 
< div  id = "c"  style = "z-index:0;" > C < / div >

CSS z-index 屬性參與規則的例子, 沒有明確定位的時候

W3C 對z-index 屬性的描述中提到在z-index 屬性僅在節點的position 屬性為relative, absolute 或者fixed 時生效.

The z-index property specifies the stack order of an element. Only works on positioned elements(position: absolute;, position: relative; or position: fixed;).

< div  id = "a"  style = "z-index:2;" > A < / div > 
< div  id = "b"  style = "position:relative;z-index:1;" > B < / div > 
< div  id = "c"  style = "position:relative;z-index:0;" > C < / div >

CSS z-index 屬性參與規則的例子, 明確定位的節點才能使用z-index 屬性

默認值規則

如果所有節點都定義了position:relative. z-index 為0 的節點與沒有定義z-index 在同一層級內沒有高低之分; 但z-index 大於等於1 的節點會遮蓋沒有定義z-index 的節點; z-index 的值為負數的節點將被沒有定義z-index 的節點覆蓋.

< div  id = "a"  style = "position:relative;z-index:1;" > A < / div > 
< div  id = "b"  style = "position:relative;z-index:0;" > B < / div > 
< div  id = "c"  style = "position:relative;" > C < / div > 
< div  id = "d"  style = "position:relative;z-index:0;" > D < / div >

CSS z-index 屬性默認值規則的例子

通過檢查我們還發現, 當position 設為relative, absolute 或者fixed, 而沒有設置z-index 時, IE8 以上和W3C 瀏覽器(下文我們統稱為W3C 瀏覽器) 的z-index 默認值是auto, 但IE6和IE7 是0.

從父規則

如果A, B 節點都定義了position:relative, A 節點的z-index 比B 節點大, 那麼A 的子節點必定覆蓋在B 的子節點前面.

< div  id = "a"  style = "position:relative;z-index:1;" > 
	< div  id = "a-1" > A-1 < / div > 
< / div >
 
< div  id = "b"  style = "position:relative;z-index:0;" > 
	< div  id = "b-1" > B-1 < / div > 
< / div >

CSS z-index 屬性從父規則的例子, 子節點不設定層級

如果所有節點都定義了position:relative, A 節點的z-index 和B 節點一樣大, 但因為順序規則, B 節點覆蓋在A 節點前面. 就算A 的子節點z-index 值比B 的子節點大, B 的子節點還是會覆蓋在A 的子節點前面.

< div  id = "a"  style = "position:relative;z-index:0;" > 
	< div  id = "a-1"  style = "position:relative;z-index:2;" > A-1 < / div > 
< / div >
 
< div  id = "b"  style = "position:relative;z-index:0;" > 
	< div  id = "b-1"  style = "position:relative;z-index:1;" > B-1 < / div > 
< / div >

CSS z-index 屬性從父規則的例子, 不可逾越的層級

很多人將z-index 設得很大, 9999 什麼的都出來了, 如果不考慮父節點的影響, 設得再大也沒用, 那是無法逾越的層級.

層級樹規則

可能你會覺得在DOM 結構中的兄弟節點會拎出來進行比較並確定層級, 其實不然.

< div  id = "a"  style = "position:relative;z-index:2;" > 
	< div  id = "a-1"  style = "position:relative;z-index:0;" > A-1 < / div > 
< / div >
 
< div  id = "b" > 
	< div  id = "b-1"  style = "position:relative;z-index:1;" > B-1 < / div > 
< / div >

CSS z-index 屬性層級樹規則的例子

我們認為同時將position 設為relative, absolute 或者fixed, 並且z-index 經過整數賦值的節點, 會被放置到一個與DOM 不一樣的層級樹里面, 並且在層級樹中通過對比z-index 決定顯示的層級. 上面的例子如果用層級樹來表示的話, 應該如下圖所示.

CSS z-index 的層級樹

圖中雖然A-1 ( z-index:0 )的值比B-1 ( z-index:1 )小,但因為在層級樹里A ( z-index:2 )和B-1在一個層級,而A的值比B-1大,根據從父規則, A-1顯示在B-1前面.

參與規則 2

前面提到的參與規則認為只要節點的position 屬性為relative, absolute 或者fixed, 即可參與層級比較, 其實不准確. 如果所有節點都定義了position:relative, 並且將z-index 設為整數值, 根據從父規則, 父節點的層級決定了子節點所在層級.

< div  id = "a"  style = "position:relative;z-index:0;" > 
	< div  id = "a-1"  style = "position:relative;z-index:100;" > A-1 < / div > 
< / div >
 
< div  id = "b" > 
	< div  id = "b-1"  style = "position:relative;z-index:0;" > 
		< div  id = "b-1-1"  style = "position:relative; z-index:10;" > B-1-1 < / div > 
	< / div > 
< / div >
 
< div  id = "c"  style = "position:relative;z-index:0;" > 
	< div  id = "c-1" > 
		< div  id = "c-1-1" > 
			< div  id = "c -1-1-1"  style = "position:relative;z-index:1;" > C-1-1-1 < / div > 
		< / div > 
	< / div > 
< / div >

例子中A, B-1, C-1-1 作為父節點, z-index 的值相同, 根據順序規則, C-1-1 在B-1 之前, B-1 在A 之前; 又根據從父規則, 無論子節點的z-index 值是什麼, C-1-1-1 在B-1-1 之前, B-1-1 在A-1 之前.

CSS z-index 屬性參與規則2 的例子, 所有節點參與層級比較

如果我們將所有父節點的z-index 屬性去除, 詭異的事情發生了. IE6 和IE7 瀏覽器顯示效果不變, 而W3C 瀏覽器的子節點不再從父, 而是根據自身的z-index 確定層級.

< div  id = "a"  style = "position:relative;" > 
	< div  id = "a-1"  style = "position:relative;z-index:100;" > A-1 < / div > 
< / div >
 
< div  id = "b" > 
	< div  id = "b-1"  style = "position:relative;" > 
		< div  id = "b-1-1"  style = "position:relative;z-index:10; " > B-1-1 < / div > 
	< / div > 
< / div >
 
< div  id = "c"  style = "position:relative;" > 
	< div  id = "c-1" > 
		< div  id = "c-1-1" > 
			< div  id = "c-1-1-1 "  style = "position:relative;z-index:1;" > C-1-1-1 < / div > 
		< / div > 
	< / div > 
< / div >

根據默認值規則, IE6 / IE7 和W3C 瀏覽器上的元素存在z-index 默認值的區別. 我們相信, 僅當position 設為relative, absolute 或者fixed, 並且z-index 賦整數值時, 節點被放置到層級樹; 而z-index 為默認值時, 只在document 兄弟節點間比較層級. 在W3C 瀏覽器中, A, B-1 和C-1-1 的z-index 均為auto, 不參與層級比較.

CSS z-index 屬性參與規則2 的例子, z-index 為auto 的節點不參與層級比較

而在IE6 和IE7 中, 因為z-index 的默認值是0, 所以也參與了層級比較.

CSS z-index 屬性參與規則2 的例子, IE6 和IE7 中z-index 默認為 0

設置了position 而沒有z-index 的節點雖然不參與層級樹的比較, 但還會在DOM 中與兄弟節點進行層級比較.

< div  id = "a"  style = "position:relative;" > 
	< div  id = "a-1"  style = "position:relative;z-index:100;" > A-1 < / div > 
< / div >
 
< div  id = "b" > 
	< div  id = "b-1" > 
		< div  id = "b-1-1"  style = "position:relative;z-index:10;" > B-1-1 < / div > 
	< / div > 
< / div >
 
< div  id = "c"  style = "position:relative;" > 
	< div  id = "c-1" > 
		< div  id = "c-1-1" > 
			< div  id = "c-1-1-1 "  style = "position:relative;z-index:1;" > C-1-1-1 < / div > 
		< / div > 
	< / div > 
< / div >

我們對上個例子改造一下, 將B-1 的position 屬性刪除​​後, W3C 瀏覽器顯示如下圖. 根據定位規則, A 和C-1-1 會顯示在B-1 的前面; 而根據順序規則, C-1-1 又顯示在A 前面.

CSS z-index 屬性參與規則2 的例子, position 為auto 的節點不參與層級樹比較, 但仍參與DOM 兄弟節點間的層級比較, W3C 瀏覽器

在IE6和IE7中,因為A和C-1-1設置了position:relative ,而且z-index的默認值為0,所以也參與層級樹比較,所以有如下效果.

CSS z-index 屬性參與規則2 的例子, position 為auto 的節點不參與層級樹比較, 但仍參與DOM 兄弟節點間的層級比較, IE6 和IE7

總結

瀏覽器節點顯示層級是一個費力的活, 今天你覺得A 區塊會永遠置頂, 但明天因為需求變動, 突然出現B 元素需要置頂. 一層一層往上堆砌, 某天回頭一看, 發現很多區塊交錯在一起, 而且他們的值一個比一個大, 根本搞不清頭緒. 我覺得在操刀幹活之前, 最好先將position, z-index 和層級的關係搞搞清楚, 以免後患無窮.

另外, 非情非得已, 切勿用JavaScript 計算z-index, 並將某個節點的z-index 設置成所有節點中層級最高.

因為篇幅太長, 本文僅從節點屬性角度進行討論, 沒有涉及select 和iframe 等特殊頁面節點考慮, 如果有機會下次再為大家分享.

廣告

2 thoughts on “CSS z-index 属性的使用方法和層級概念

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s