你須要瞭解的z-index世界

z-index的重要性

在我看來,z-index 給了咱們平常工做中以極大的幫助,咱們用它來定義元素的層疊級別(stack level)。受益於它,你能作Popup, DropDown, Tips, 圖文替換等等。css

在開始本篇以前,或許咱們要先了解一下關於z-index的基本信息。瀏覽器

W3C這樣描述

每一個元素都具備三維空間位置,除了水平和垂直位置外,還能在 「Z軸」 上層層相疊、排列。元素在 「Z軸」 方向上的呈現順序,由層疊上下文和層疊級別決定。網絡

在文檔中,每一個元素僅屬於一個層疊上下文。元素的層疊級別爲整型,它描述了在相同層疊上下文中元素在 「Z軸」 上的呈現順序。性能

同一層疊上下文中,層疊級別大的顯示在上,層疊級別小的顯示在下,相同層疊級別時,遵循後來居上的原則,即其在HTML文檔中的順序。測試

不一樣層疊上下文中,元素呈現順序以父級層疊上下文的層疊級別來決定呈現的前後順序,與自身的層疊級別無關。字體

z-index語法和應用

z-index: auto | <integer>

z-index 接受的屬性值爲:關鍵字auto和整數,整數能夠是負值(Firefox2.0及以前不支持負值)。url

須要注意的是 z-index 雖然很給力,卻只能應用於定位元素(即設置了 position 屬性爲非 static 值),其它狀況下,z-index 將被忽略。spa

對於定位元素而言,z-index 意味着:code

  • 肯定該元素在當前層疊上下文中的層疊級別。
  • 肯定該元素是否建立了一個新的局部層疊上下文。

建立層疊上下文

在規範中說明:當某個元素的 z-index 未顯式定義或者被指定爲 auto 時,該元素不會產生新的局部層疊上下文。也就是說它能夠和兄弟,祖先,後輩元素處在同一個堆疊上下文中,它們被放在一塊兒比較層疊級別,兒子能夠蓋住祖先,父親也能夠蓋住兒子,兒子甚至能夠越過祖先,蓋住祖先的兄弟,在層疊上下文中,它們是並級的關係。來看這樣一個例子 DEMO1: z-index與建立層疊上下文orm

值得高興的是,大部分瀏覽器都實現了這個特性;不過在IE6/7下,不論 z-index 值是否被顯式定義,都將產生新的局部層疊上下文,也就是說子元素不能夠越過是定位元素的父親,子元素都處在新建立的局部層疊上下文中,只能在內部進行層疊級別的比較。

深刻淺出

某區域內有個浮層提示或者下拉菜單,因而可能須要遮住該區域之下的區域。

HTML

<div class="a">
    ...
    <div class="tips">我是一個簡陋的浮層提示</div>
</div>
<div class="b">
    ...
</div>

CSS

.a{position:relative;}
.tips{position:absolute;z-index:99;}

如上HTML/CSS代碼,很顯然,浮層 tips 將能夠覆蓋在其父級元素 a 的兄弟元素 b 之上。

因而你的意圖獲得實現,效果以下 圖一

(圖一)

這是具體的實現例子 DEMO2: z-index實現元素層疊

不過很顯然,從 DEMO2 來看,你依然沒法準確的判斷出在各瀏覽器下,tips 能蓋住 b 是由於其父級的定位仍是自己的定位。

可是咱們能夠作這樣一個測試,咱們讓 b 也擁有定位,Code以下:

CSS

.a{position:relative;}
.tips{position:absolute;z-index:99;}
.b{position:relative;}

這段代碼run完以後,就比較糾結了,你能獲得的效果將會以下 圖二

(圖二)

固然要給出具體實現 DEMO3: 驗證建立局部層疊上下文

首先,咱們來解讀一下這個例子:由於 ab 都是 relative 且沒有定義 z-index (等同於z-index:auto),根據後來居上的原則,此時 b 的層疊級別是要高於 a 的,意思就是說 a 是沒法遮住 b 的。不過從 DEMO3 中,咱們看到 a 的子元素 tips 遮住了 b,這就表示 tips 能越過它,因此能夠判斷出 a 沒有建立新的局部層疊上下文。很明顯,這是徹底吻合標準對此的定義。

不過這是在非IE6/7之下結果。在IE6/7下,咱們看到 tips 並沒能遮住 b,也就是說 tips 沒法越過父級,由於 a 建立了新的局部層疊上下文,而 a 的層疊級別又比 b 低,因此 tips 沒法遮住 b,這也就是在IE6/7下常出現覆蓋Bug的根源。

結合 DEMO2DEMO3,你能很確定的得出如下結論:

  • 當定位元素沒有顯式定義z-index值時,不會建立新的局部層疊上下文
  • 子元素有可能和祖先的兄弟或者祖先兄弟的子元素處在同一個層疊上下文中

在實際工做中,有些狀況多是你沒注意或者已然存在的。好比你事先可能並不知道 b 也是定位元素,或者因爲某些緣由,你須要將其設置爲定位元素,因而可能出現各類兼容問題。若是你不瞭解 z-index 是如何建立局部層疊上下文,且又沒注意到IE6/7的實現錯誤,那麼處理起這樣的問題將會讓你深陷泥潭。

因此在實際的場景中,若是是爲了相互覆蓋而設置爲定位,那麼顯式的定義 z-index 值,將可避免出現建立新局部層疊上下文差別。

若是須要越過祖先和其它區塊內部元素進行相互層疊,那麼考慮IE6/7的狀況,也應該儘可能避免給父級元素進定位。

opacity與層疊上下文

咱們知道 opacity 屬性是用來設置元素不透明度的。但可能知道 opacity 和層疊上下文有關的很少,不過不要緊,這裏咱們簡單聊聊這個話題,有兩點必須注意:

  • 當opacity值小於1時,該元素會建立新的局部層疊上下文,也就是說它能夠和定位元素進行層疊層別比較
  • 當opacity值小於1時,該元素擁有層疊級別且至關於z-index:0或auto,但不能定義 z-index ,除非自己是定位元素

簡單來講,當一個普通的元素定義了 opacity 的值小於1時(好比 opacity:.5),那麼該元素的層疊級別將會高於普通元素,其效果類同於定位元素沒有顯式定義 z-index 的狀況,惟一的區別是沒有顯式定義 z-index 的定位元素不會產生局部層疊上下文,而定義了 opacity 值小於1的元素會產生新的局部層疊上下文。

opacity猜測

假定咱們有 a, b, c 三個元素,它們相互層層覆蓋在一塊兒,若是這時將 a 元素定義爲 opacity:.8,你知道結果會怎樣嗎?

HTML

<div class="a">a</div>
<div class="b">b</div>
<div class="c">c</div>

CSS

.a,.b,.c{width:100px;height:100px;}
.a{opacity:.8;background:#999;}
.b{margin:-70px 0 0 30px;background:#090;}
.c{margin:-70px 0 0 60px;background:#f00;}

若是你看明白了我對於 opacity 與層疊上下文的描述,相信你能夠猜到結果,是的,a 元素將會覆蓋 bc 元素,雖然它在HTML文檔中出如今 bc 以前,且不是定位元素。

必須看看具體的示例不是麼?DEMO4: opacity與局部層疊上下文猜測

若是咱們將 bc 設置爲定位元素,又將會如何呢?

CSS

.a,.b,.c{width:100px;height:100px;}
.a{opacity:.8;background:#999;}
.b{position:relative;margin:-70px 0 0 30px;background:#090;}
.c{position:relative;margin:-70px 0 0 60px;background:#f00;}

不急,咱們能夠接着看示例 DEMO5: opacity與局部層疊上下文猜測2

DEMO4DEMO5 兩例,咱們能夠驗證:當一個普通元素定義了 opacity 爲小於1的值時,該元素將像定位元素同樣擁有層疊級別,能夠覆蓋普通元素,而且其層疊級別與未顯式定義 z-index 的定位元素同樣。

opacity建立局部層疊上下文

與未顯式定義 z-index 的定位元素惟一不一樣的是 opacity 值小於1的元素會建立局部層疊上下文。

建立局部層疊上下文意味着什麼,前文咱們已經詳述過。因此再也不贅述,這裏只給一個示例用以驗證該特性。先奉上代碼:

HTML

<div class="a">a
    <div class="d">d</div>
</div>
<div class="b">b</div>
<div class="c">c</div>

CSS

.a,.b,.c,.d{width:100px;height:100px;}
.a{opacity:.8;background:#999;}
.b{position:relative;margin:-70px 0 0 30px;background:#090;}
.c{position:relative;margin:-70px 0 0 60px;background:#f00;}
.d{position:absolute;z-index:99;height:50px;background:#090;}

你能夠先看看具體結果 DEMO6: opacity建立新局部層疊上下文

你會發現雖然 a 的子元素 dz-index 定義爲99,但 d 仍然沒法遮住 bc 元素,這是由於 a 建立了新的局部層疊上下文,d 元素沒法超越父級。

須要注意的是,此時就算 a 元素變成了定位元素,也不能改變其會建立新局部層疊上下文的命運,由於他設置了 opacity:.8

按照咱們前文所說,若是 a 沒有定義 opacity:.8 ,但卻像 bc 元素同樣設置了 relative,那麼其子元素 d 將能夠覆蓋 bc,至於這個例子就再也不奉上了,你們隨便寫個測試一下便可。

圖文替換

上述都是理論性的東西,相對枯燥,來個實際點的應用場景。

咱們聊聊圖文替換的事,相對於使用較廣的方案如:縮進正/負值(正/負text-indent)、超小字體、margin溢出、padding溢出、line-height溢出、透明字體、display:none、visibility:hidden等方案而言,使用 z-index 負值的方案,有一些明顯的優點:

  • 無需考慮是否會有性能問題類同使用上述列舉中的前幾種方案(好比使用負縮進值-9999px,雖然此時文本被移到屏幕以外或者被裁減,但仍然會繪製一個寬9999px的盒子);
  • 沒有像相似超小字體和透明字體同樣的方案會須要一些額外的hack;
  • 不像display:none方案那樣有SEO欺騙嫌疑;
  • 當圖片加載失敗時,能夠顯示文字;
  • and etc…

先來看看一個圖文替換的例子 DEMO7: 圖文替換實例

在不一樣的網絡環境下,它的表現以下 圖三

(圖三)

具體的Code很簡單:

HTML


<a href="#top" title="回到頂部"><span>TOP▲</span></a>

CSS


a,a span{display:inline-block;width:38px;height:38px;} a{background:url(images/ico.png) no-repeat;} a:hover{background-position:0 -39px;color:#fff;} a span{position:relative;z-index:-1;background-color:#eee;} a:hover span{background-color:#999;}

你會發現咱們將 span 設置爲了 z-index:-1,此時它的層疊級別將比正常的元素還要低,因此它能夠被其父元素超連接a蓋住,從而在圖片正常載入時顯示父元素的背景圖,在網絡環境很差圖片載入有問題時,顯示自身。

不少時候,要實現一個需求可能有無數種解決方案,可以適應狀況越多的方案毫無疑問會脫穎而出,這就要求咱們能夠去更多的思考,而不是更多的拷貝。

相關文章
相關標籤/搜索