淺談為什么我的 z-index 又不生效了
表面看起來,z-index 似乎是一個(gè)很簡(jiǎn)單的屬性,你給它設(shè)置哪個(gè)值,元素就會(huì)位于 z 軸的哪個(gè)位置。但它實(shí)際上并沒有我們想象的這么簡(jiǎn)單,這個(gè)屬性背后是一系列決定元素所在層級(jí)的規(guī)則。
在進(jìn)行今天的介紹前,我們先列出三個(gè)問題,如果你能一眼看出它們的解決方案,那么恭喜你掌握了z-index,也就不需要閱讀本文了;如果不行,那么耐心看完本文,相信能找到答案。
三個(gè)自測(cè)問題
- 問題一:為什么
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 簡(jiǎn)介
沒有使用 z-index 的時(shí)候,元素的層疊關(guān)系由2個(gè)因素決定:
- 該元素的
position是否是static,如果是static,那么這個(gè)元素就稱為non-positioned;反之,如果position值是relative,absolute,fixed, 或sticky則稱positioned。positioned元素享受特權(quán),會(huì)覆蓋non-positioned元素。而non-positioned元素中,有float樣式的元素覆蓋沒有float的。 - 元素的“出場(chǎng)”順序 —— 即在html中的順序,同類型元素遵循后來者居上的原則。
z-index 屬性設(shè)定了一個(gè)定位元素及其后代元素或 flex 項(xiàng)目的 z-order。當(dāng)元素之間重疊的時(shí)候,z-index 較大的元素會(huì)覆蓋較小的元素在上層進(jìn)行顯示。
所謂 z-index,只有在以下場(chǎng)景適用。分別為:
- 首先,
z-index這個(gè)屬性并不是在所有的元素上都有效果。它僅僅只在positioned元素上有效果。 - 要判斷元素在
z軸上的堆疊順序,并不僅僅是直接比較兩個(gè)元素的 z-index 值的大小,同時(shí),這個(gè)堆疊順序還由元素的層疊上下文和層疊等級(jí)共同決定。
層疊上下文
z-index 存在的一個(gè)背景是 Stacking Context ,中文常譯作層疊上下文(其實(shí)數(shù)據(jù)結(jié)構(gòu)中的棧的單詞也是 stack,所以層疊上下文中已經(jīng)蘊(yùn)含了后來者居上的意思)。
層疊上下文,是HTML中一個(gè)三維的概念。在 CSS2.1 規(guī)范中,每個(gè)盒模型的位置是三維的,分別是平面畫布上的X軸,Y軸以及表示層疊的Z軸。
一般情況下,元素在頁(yè)面上沿 X軸 和 Y軸 平鋪,我們是察覺不到它們?cè)?code>Z軸上的層疊關(guān)系。而一旦元素發(fā)生堆疊,這時(shí)就能發(fā)現(xiàn)某個(gè)元素可能覆蓋了另一個(gè)元素或者被另一個(gè)元素覆蓋。
如果一個(gè)元素含有層疊上下文,(也就是說它是層疊上下文元素),我們可以理解為這個(gè)元素在Z軸上就“高人一等”,最終表現(xiàn)就是它離屏幕觀察者更近。

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

