css z-index屬性

原文地址:http://www.neoease.com/css-z-index-property-and-layering-tree/css

CSS 中的 z-index 屬性用於設置節點的堆疊順序, 擁有更高堆疊順序的節點將顯示在堆疊順序較低的節點前面, 這是咱們對 z-index 屬性廣泛的認識. 與此同時, 咱們老是對堆疊順序捉摸不透, 將 z-index 的值設得很大也未必能將節點顯示在最前面. 本文將經過一些例子對 z-index 的使用方法進行分析, 而且爲各位帶入 z-index 層級樹的概念.html

 

這個星期咱們團隊作了一次內部的技術分享, 南瓜小米粥爲咱們分享了他對 CSS z-index 的理解和引入層級樹這個概念. 這個分享的現場效果很好, 因此我也將 z-index 和層級樹話題搬到博客來談一談.瀏覽器

本文談及多個影響節點顯示層級的規則, 其中用到的全部例子所有羅列在《position 屬性和 z-index 屬性對頁面節點層級影響的例子》中.app

目錄

順序規則

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

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

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

定位規則

若是將 position 設爲 static, 位於文檔流後面的節點依然會遮蓋前面的節點浮動, 因此 position:static 不會影響節點的遮蓋關係.ide

<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.spa

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

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

上面互相覆蓋在何時用到這樣的實現? 看起來偏門, 其實很經常使用, 好比說, 電子商務網站側欄的類目展現列表就能夠用這個技巧來實現.code

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

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

參與規則

咱們嘗試不用 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 等特殊頁面節點考慮, 若是有機會下次再爲你們分享.

相關文章
相關標籤/搜索