你需要了解的z-index世界
原文地址:你需要了解的z-index世界 by @doyoe
z-index的重要性
在我看來,z-index
給了我們日常工作中以極大的幫助,我們用它來定義元素的層疊級別(stack level)。受益於它,你能做Popup, DropDown, Tips, 圖文替換等等。
在開始本篇之前,或許我們要先了解一下關於z-index的基本資訊。
W3C這樣描述
每個元素都具有三維空間位置,除了水平和垂直位置外,還能在 "Z軸" 上層層相疊、排列。元素在 "Z軸" 方向上的呈現順序,由層疊上下文和層疊級別決定。
在文件中,每個元素僅屬於一個層疊上下文。元素的層疊級別為整型,它描述了在相同層疊上下文中元素在 "Z軸" 上的呈現順序。
同一層疊上下文中,層疊級別大的顯示在上,層疊級別小的顯示在下,相同層疊級別時,遵循後來居上的原則,即其在HTML文件中的順序。
不同層疊上下文中,元素呈現順序以父級層疊上下文的層疊級別來決定呈現的先後順序,與自身的層疊級別無關。
z-index語法和應用
z-index: auto | <integer>
z-index
接受的屬性值為:關鍵字auto和整數,整數可以是負值(Firefox2.0及之前不支援負值)。
需要注意的是 z-index
雖然很給力,卻只能應用於定位元素(即設定了 position
屬性為非 static
值),其它情況下,z-index
將被忽略。
對於定位元素而言,z-index
意味著:
- 確定該元素在當前層疊上下文中的層疊級別。
- 確定該元素是否建立了一個新的區域性層疊上下文。
建立層疊上下文
在規範中說明:當某個元素的 z-index
未顯式定義或者被指定為 auto
時,該元素不會產生新的區域性層疊上下文。也就是說它可以和兄弟,祖先,後輩元素處在同一個堆疊上下文中,它們被放在一起比較層疊級別,兒子可以蓋住祖先,父親也可以蓋住兒子,兒子甚至可以越過祖先,蓋住祖先的兄弟,在層疊上下文中,它們是並級的關係。來看這樣一個例子 DEMO1
: z-index與建立層疊上下文
值得高興的是,大部分瀏覽器都實現了這個特性;不過在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
: 驗證建立區域性層疊上下文。
首先,我們來解讀一下這個例子:因為 a
和 b
都是 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的根源。
結合 DEMO2
和 DEMO3
,你能很肯定的得出以下結論:
- 當定位元素沒有顯式定義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
元素將會覆蓋 b
和 c
元素,雖然它在HTML文件中出現在 b
和 c
之前,且不是定位元素。
必須看看具體的示例不是麼?DEMO4
: opacity與區域性層疊上下文猜想。
如果我們將 b
和 c
設定為定位元素,又將會如何呢?
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。
從 DEMO4
和 DEMO5
兩例,我們可以驗證:當一個普通元素定義了 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
的子元素 d
將 z-index
定義為99,但 d
仍然無法遮住 b
和 c
元素,這是因為 a
建立了新的區域性層疊上下文,d
元素無法超越父級。
需要注意的是,此時就算 a
元素變成了定位元素,也不能改變其會建立新區域性層疊上下文的命運,因為他設定了 opacity:.8
。
按照我們前文所說,如果 a
沒有定義 opacity:.8
,但卻像 b
和 c
元素一樣設定了 relative
,那麼其子元素 d
將可以覆蓋 b
和 c
,至於這個例子就不再奉上了,大家隨便寫個測試一下即可。
圖文替換
上述都是理論性的東西,相對枯燥,來個實際點的應用場景。
我們聊聊圖文替換的事,相對於使用較廣的方案如:縮排正/負值(正/負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蓋住,從而在圖片正常載入時顯示父元素的背景圖,在網路環境不好圖片載入有問題時,顯示自身。
很多時候,要實現一個需求可能有無數種解決方案,能夠適應情況越多的方案毫無疑問會脫穎而出,這就要求我們可以去更多的思考,而不是更多的拷貝。
相關文章
- 你需要了解API介面API
- 你需要了解的 HTTP Status CodeHTTP
- 你需要了解的HTTP協議HTTP協議
- 你需要了解的 Node.js 模組Node.js
- 關於redis,你需要了解的幾點!Redis
- 130 個你需要了解的 vim 命令
- 學習 webpack 前,你需要了解的那些概念Web
- 六款你需要了解的實用軟體
- 關於 Web Workers 你需要了解的 7 件事Web
- 你需要了解的前端測試“金字塔”前端
- 接觸Mac初期,你需要了解的那點事Mac
- 超過 130 個你需要了解的 vim 命令
- 超過130個你需要了解的vim命令
- 學習Flutter,你需要了解的Dart 編碼規範FlutterDart
- 11種你需要了解的物聯網(IoT)協議協議
- (轉)超過 130 個你需要了解的 vim 命令
- 10 個你需要了解的最佳 javascript 開發實踐JavaScript
- 關於 React19,你需要了解的前因後果React
- 說說你對z-index的理解Index
- 你真的需要了解多種程式語言嗎?
- 開發者需要了解的WebKitWebKit
- 你需要了解的伺服器託管收費標準伺服器
- 入門Java你需要了解的幾個知識要點!Java
- [譯] 關於 CSS 變數,你需要了解的一切CSS變數
- 初學 Spring Boot,你需要了解的 7 樣東西Spring Boot
- 20 道 Spring Boot 面試題你需要了解下Spring Boot面試題
- 微服務架構盛行的時代,你需要了解點 Spring Boot微服務架構Spring Boot
- 關於響應式佈局,你需要了解的知識點
- 你最需要了解的H3C交換機埠安全模式模式
- 10 個你需要了解的 Linux 網路和監控命令Linux
- 面試 Netflix 前,你至少需要了解以下內容面試
- 小白必看!入門嵌入式你需要了解這些!
- 前端需要了解的http知識前端HTTP
- 前端需要了解的色彩知識前端
- 從 Python 2 切換到 Python 3 你所需要了解的Python
- 你需要了解下Android View的更新requestLayout與重繪invalidateAndroidView
- 中文文字分類:你需要了解的10項關鍵內容文字分類
- 關於有效客戶關係管理,你需要了解的一切