深入CSS屬性(九):z-index

zuo發表於2014-10-21

如果你不是一名csser新手,想必你對z-index的用法應該有個大致的瞭解了吧,z-index可以控制定位元素在垂直於螢幕方向(Z 軸)上的堆疊順序,本文不去講述基本的API如何使用,而是去更深入的瞭解z-index是如何工作的,使用z-index的時候有哪些問題,以及z-index在日常開發中的使用。 下面我們通過一個例子來引入今天的正文,程式碼示例:

<style type="text/css">
	.red, .green, .blue {
		position: absolute;
		width: 100px;
		height: 100px;
		text-align: center;
		line-height: 100px;
		color: #fff;
	}
	.red {
		background-color: red;
		z-index: 1;
	}
	.green {
		background-color: green;
		top: 70px;
		left: 70px;
	}
	.blue {
		background-color: blue;
		top: 140px;
		left: 140px;
	}
</style>  
<div>
	<span class="red">Red box</span>
</div>
<div>
	<span class="green">Green box</span>
</div>
<div>
	<span class="blue">Blue box</span>
</div>

如下圖: z-index_01

上述程式碼通俗易懂,下面有個問題請大家思考: 在遵循下述規則的情況下,如何使用紅色span元素在green和blue元素後面?

1) 不能以任何方式更改html標記;

2) 不能增加或改變任何元素的z-index屬性;

3) 不恩增加或改變任何元素的position屬性;

請大家思考,這個問題改如何解決?說明其原因? ----------------------------------- 分割線 ----------------------------------------------

一、z-index 黃金法則及stack context

1) 一個box和它的父親有相同的堆疊級別(stack level),除非該box被通過z-index屬性賦予了不同的stack level;

2) z-index屬性只適應於position屬性為relative、absolute、fixed的元素物件;

3) 給一個被定位(positioned)元素設定小於1的opacity屬性值,意味著建立了一個堆疊上下文(stack context),就像給該元素增加了一個z-index值;

4) 對於一個被positioned box,如果指定了z-index屬性,意味著:

->該box的stack level 在當前的stack context中;

->該box建立了個本地stack context;

5) 如果box沒有指定z-index,元素將被按下面的順序堆疊(stacked)(從後到前):

-> 正常流中的boxes,根據在原始碼中的序列;

-> 浮動boxes;

-> computed後display屬性值為inline/inline-block/inline-table的boxes;

-> positioned boxes 和boxes 設定opacity值小於1,根據在原始碼中的序列;

 

 

因此,當我們給一個positioned元素設定了z-index時,我們做了兩件事:

1) 該元素與在它前面或者後面的元素共享著相同的stack context,這也就是我們改變z-index的值,元素會移動其他元素前後者後的原因。

2) 為該元素內的任何元素建立了一個新的stack context,一旦你建立了一個stack context,內部的任何有(stack context)的任何層都會停留在這個stack context。 通過上述的黃金法則,也許你已經知道上面那個問題的答案了。在黃金法則裡,我們提到了個新名詞“stack context”,下面我們通過一個例項來介紹它:

<!DOCTYPE html>
<html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>z-index example</title>
</head>
<body>
<h1>Header</h1> 	
<p>I am paragraph. <em> I am em</em></p>			
</body>
</html>

一個很特殊的情況是,在一個document中,沒有任何定位,document有且只有一個堆疊環境 - 通過HTML建立。 下面我們給上例新增如下樣式:

		h1, p {
			position: relative;
		} 
		h1 {
			z-index: 2;
		}
		p {
			z-index: 1;
		}

在這種情況下,h1,p都建立了一個stack context,這兩個stack context都在document的stack context內。增加樣式後h1在p元素之上。如果我們給em元素增加如下樣式結果又會怎樣:

		h1, p, em {
			position: relative;
		} 
		h1 {
			z-index: 2;
			background-color: #f0f;
		}
		p {
			z-index: 1;
			background-color: #00f;
			line-height: 40px;
		}
		em {
			z-index: 1;
			background-color: #f00;
		}

增加此樣式後em建立了stack context,由於em的z-index屬性,它的內部的text比p標籤中的其它text更接近使用者。因為它是在p的stack context內部,它是一直比h1中的text低的。 注意:如果你增加z-index的值,是不能使用em位於h1之上的。如果你想一個context的元素位於另一個context中的元素之上,你必須提升整個context或者設定它們為相同的context。 下面是兩種解決方案: 方案一:

		h1, p, em {
			position: relative;
		} 
		h1 {
			z-index: 2;
			background-color: #f0f;
		}
		p {
			/* raise the entire context,p and em 都在h1 之上了*/
			z-index: 3;
			background-color: #00f;
			line-height: 40px;
			margin-top: -40px;
		}
		em {
			z-index: 1;
			background-color: #f00;
		}

方案二:

		h1, p, em {
			position: relative;
		} 
		h1 {
			z-index: 2;
			background-color: #f0f;
		}
		p {
			background-color: #00f;
			line-height: 40px;
			margin-top: -40px;
		}
		em {
			/*  put them into the same context */
			z-index: 2;
			background-color: #f00;
		}

二、建立stack context及注意事項

那麼建立stack context的方式有哪些?

1) When an element is the root element of a document (theelement)

2) When an element has a position value other than static and a z-index value other than auto

3) When an element has an opacity value less than 1

Update: In addition to opacity, several newer CSS properties also create stacking contexts. These include: transforms, filters, css-regions, paged media, and possibly others. As a general rule, it seems that if a CSS property requires rendering in an offscreen context, it must create a new stacking context.

 

In WebKit, styling a box with position:fixed or -webkit-overflow-scrolling:touch implicitly creates a stacking context, just like adding a z-index value.

Also, be aware of these CSS3 “triggers”:

transform != none

transform-style: preserve-3d

filter != none clip-path, mask

Lastly, even though a relatively positioned element without a z-index set does not establish a stacking context… A common IE bug, often seen in drop-down menus, is that any relatively positioned element that has haslayout set to true establishes a stacking context. One may visualize this bug by setting [A] and [B] to position:relative, while [a] gets position:relative; z-index:1. Now, dragging [A] under [B] hides [a] - in Internet Explorer, that is. Any positioned child with a z-index is caught by this wrong stacking context of its parent.

三、z-index在某些瀏覽器中的問題

1) IE6中的 select元素是一個視窗控制元件,所以它總是出現在層疊順序的頂部而不會顧及到自然層疊順序、position屬性或者是z-index。可以在div元素上新增一個iframe設定為position:absolute,並設定div的z-index比iframe的高。

2) 因父容器(元素)被定位的緣故,IE6/7會錯誤的對其stacking context進行重置。

3) 在Firefox2版本中,一個負的z-index值會使元素位於stacking context的後面,而不是位於公認的背景和邊框這樣的元素stacking context之前。 本文到此結束,最後附上本文開始時提出的問題的答案:

/* add this */
div:first-child {
opacity: .99;
}

感謝您的閱讀,文中不妥之處,還望批評指正。

四、參考連結:

Find out how elements stack and start using low z-index values

The Z-Index CSS Property: A Comprehensive Look

Elaborate description of Stacking Contexts

Overlapping And ZIndex

CSS/Properties/z-index

Understanding CSS z-index(MDN)

What No One Told You About Z-Index

測試Demo:

 

原載於: Benjamin 
本文連結: http://www.zuojj.com/archives/904.html 
如需轉載請以連結形式註明原載或原文地址。