淺談為什么我的 z-index 又不生效了
表面看起來,z-index 似乎是一個很簡單的屬性,你給它設(shè)置哪個值,元素就會位于 z 軸的哪個位置。但它實際上并沒有我們想象的這么簡單,這個屬性背后是一系列決定元素所在層級的規(guī)則。
在進行今天的介紹前,我們先列出三個問題,如果你能一眼看出它們的解決方案,那么恭喜你掌握了z-index,也就不需要閱讀本文了;如果不行,那么耐心看完本文,相信能找到答案。
三個自測問題
- 問題一:為什么
z-index數(shù)值更大,但Content沒有在Box 2之上?
<div id="box1">
Box 1
</div>
<div id="content">
Content <br/>
z-index: 2;
</div>
<div id="box2">
Box 2 <br/>
z-index: 1;
</div>
div {
padding: 25px;
font-size: larger;
}
#box1 {
background-color: chocolate;
width: 200px;
height: 100px;
margin-bottom: -50px;
}
#content {
background-color: gold;
width: 300px;
height: 200px;
z-index: 2;
}
#box2 {
background-color: cyan;
width: 200px;
height: 100px;
margin-top: -50px;
z-index: 1;
}

- 問題二:明明
z-index數(shù)值更小,為什么Content這次反而在Box 2之上了?
<div id="box1">
Box 1
</div>
<div id="content">
Content <br/>
transform: rotate(90deg); <br/>
z-index: 1;
</div>
<div id="box2">
<br/>
Box 2 <br/>
z-index: 2;
</div>
div {
padding: 25px;
font-size: larger;
}
#box1 {
background-color: chocolate;
width: 200px;
height: 100px;
margin-bottom: -10px;
}
#content {
background-color: gold;
width: 250px;
height: 200px;
z-index: 1;
transform: rotate(90deg);
}
#box2 {
background-color: cyan;
width: 200px;
height: 100px;
margin-top: -10px;
z-index: 2;
}

- 問題三:為什么明明
z-index是最大的,但Box 2-3在Content之下?
<div id="box1">
Box 1
</div>
<div id="content">
Content <br/>
z-index: 2; <br/>
position: relative;
</div>
<div id="box2">
<br/><br/>
Box 2 <br/>
z-index: 1; <br/>
position: relative;
<div id="box2-3">
Box 2-3 <br/>
z-index: 5; <br/>
position: absolute;
</div>
</div>
div {
padding: 25px;
font-size: larger;
}
#box1 {
background-color: chocolate;
width: 200px;
height: 100px;
margin-bottom: -50px;
}
#content {
background-color: gold;
width: 200px;
height: 100px;
margin-left: 50px;
z-index: 2;
position: relative;
}
#box2 {
background-color: cyan;
width: 200px;
height: 100px;
margin-top: -50px;
z-index: 1;
position: relative;
}
#box2-3 {
background-color: green;
width: 200px;
height: 100px;
padding-left: 150px;
left: 180px;
top: -50px;
z-index: 5;
position: absolute;
}

z-index 簡介
沒有使用 z-index 的時候,元素的層疊關(guān)系由2個因素決定:
- 該元素的
position是否是static,如果是static,那么這個元素就稱為non-positioned;反之,如果position值是relative,absolute,fixed, 或sticky則稱positioned。positioned元素享受特權(quán),會覆蓋non-positioned元素。而non-positioned元素中,有float樣式的元素覆蓋沒有float的。 - 元素的“出場”順序 —— 即在html中的順序,同類型元素遵循后來者居上的原則。
z-index 屬性設(shè)定了一個定位元素及其后代元素或 flex 項目的 z-order。當元素之間重疊的時候,z-index 較大的元素會覆蓋較小的元素在上層進行顯示。
所謂 z-index,只有在以下場景適用。分別為:
- 首先,
z-index這個屬性并不是在所有的元素上都有效果。它僅僅只在positioned元素上有效果。 - 要判斷元素在
z軸上的堆疊順序,并不僅僅是直接比較兩個元素的 z-index 值的大小,同時,這個堆疊順序還由元素的層疊上下文和層疊等級共同決定。
層疊上下文
z-index 存在的一個背景是 Stacking Context ,中文常譯作層疊上下文(其實數(shù)據(jù)結(jié)構(gòu)中的棧的單詞也是 stack,所以層疊上下文中已經(jīng)蘊含了后來者居上的意思)。
層疊上下文,是HTML中一個三維的概念。在 CSS2.1 規(guī)范中,每個盒模型的位置是三維的,分別是平面畫布上的X軸,Y軸以及表示層疊的Z軸。
一般情況下,元素在頁面上沿 X軸 和 Y軸 平鋪,我們是察覺不到它們在Z軸上的層疊關(guān)系。而一旦元素發(fā)生堆疊,這時就能發(fā)現(xiàn)某個元素可能覆蓋了另一個元素或者被另一個元素覆蓋。
如果一個元素含有層疊上下文,(也就是說它是層疊上下文元素),我們可以理解為這個元素在Z軸上就“高人一等”,最終表現(xiàn)就是它離屏幕觀察者更近。

構(gòu)建層疊上下文和蓋樓比較類似:
首先, <html> 元素是地平線或地基 —— 所有樓都是從地基開始蓋的
接下來,每產(chǎn)生一個層疊上下文,相當于蓋一座樓, z-index 的值相當于樓的高度
以下幾種元素可以產(chǎn)生層疊上下文:
- 元素的
position值為absolute或relative, 且z-index值不為auto(默認值). - 元素的
position值為fixed或sticky - 元素是
flexbox容器的子元素, 且z-index值不為auto(默認值) - 元素是
grid容器的子元素, 且z-index值不為auto(默認值) - 元素有
opacity值且值小于 1. - 元素有以下任意一項的值,且值不為
none:transformfilterperspectiveclip-pathmask / mask-image / mask-border
- 元素有
isolation值且值為isolate. - 元素有
mix-blend-mode值且值不為normal. - 元素有
-webkit-overflow-scrolling值且值為touch. - 其他幾種冷門的情況
第三,層疊上下文是可以嵌套的 —— 這是最容易讓人誤解的一塊。
嵌套,顧名思義就是在一個 層疊上下文 中能創(chuàng)建 另一個層疊上下文。
假如在地基上蓋一座50米高的樓(即 z-index: 50), 是否可以在樓里再蓋一棟 100米高的樓中樓呢?
當然不可能!但是你可以在這座樓里建一座 100 級階梯高的大堂。
換句話說,在嵌套的層疊上下文中,子層疊上下文被限制在了父層疊上下文中,它們的 z-index “單位”已經(jīng)不一樣了(z-index 沒有單位,這邊只是用于理解),無論子層疊上下文的 z-index 值有多大都無法突破父層疊上下文的高度。
層疊上下文小結(jié):
- 元素的第一級層疊上下文
- 特定樣式的元素可以產(chǎn)生新的層疊上下文,且z-index的值在這些元素中才有效
- 子層疊上下文的“高度”被限制在了父層疊上下文中
- 在同級層疊上下文中,沒有(有效) z-index 的元素依然遵循上一小節(jié)的規(guī)律;z-index 值相同的元素遵循后來者居上原則。
需要注意:層疊上下文嵌套 與 元素嵌套 不是一一對應的關(guān)系,一個元素所處的父層疊上下文是由內(nèi)向外找到的第一個能產(chǎn)生層疊上下文的元素所產(chǎn)生的層疊上下文。
看個例子便于理解:
<div id="div1" style="position: relative; z-index: 1">
<div id="div2" style="position: relative; z-index: 1">
所處的父層疊上下文是 div1 產(chǎn)生的層疊上下文
</div>
<div id="div3">
<div id="div4" style="position: relative; z-index: 2">
所處的父層疊上下文也是 div1 產(chǎn)生的層疊上下文
</div>
</div>
</div>
雖然 div4 外面還有層 div3,但是由于 div3 不能產(chǎn)生層疊上下文,所以 div4 所處的父層疊上下文也是 div1 (產(chǎn)生的層疊上下文) —— 雖然在html元素層級中 div4 比 div2 更深了一級,但是 div4 與 div2 在層疊上下文層面上是同級的,因此它們可以相互比較 z-index 值來決定誰在上面。
三個問題的解答
學習完上面的 z-index 相關(guān)知識點,我們來回答開頭提出的三個問題。
-
第一個問題中
z-index不生效的原因在于這三個元素都不能產(chǎn)生層疊上下文,因此z-index值對它們不生效 —— 根據(jù)出場順序決定了Content處在Box 2之下。 -
第二個問題的
Box 2不能產(chǎn)生層疊上下文,因此z-index同樣是無效的;Content因為使用了transform屬性,產(chǎn)生了層疊上下文,相當于蓋了一座 1 米高的樓(z-index: 1) -
Box 2與Content在同一級層疊上下文中,且Box 2的z-index比較小, 因此Box 2在Content之下;且Box 2-3在Box 2的層疊上下文下新建了個子層疊上下文,因此Box 2-3的高度被限制在了Box 2之內(nèi),因此Box 2-3的z-index再高也沒用。
到此這篇關(guān)于淺談為什么我的 z-index 又不生效了的文章就介紹到這了,更多相關(guān)z-index不生效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
- 設(shè)置z-index時必須要固定位置,這樣設(shè)置它的值時才能奏效(例如 position:absolute;)下面是示例代碼,在ff3.5.5和ie5.5~ie8.0RC1中通過,大家可以嘗試著不固定其位置試試2009-11-26

