以往,由於自己使用z-index
的頻率不大,所以對這個CSS屬性存在比較片面的認識。一直認為z-index
就是用來描述定義一個元素在屏幕Z軸
上的堆疊順序。z-index
值越大在Z軸
上就越靠上,也就是離屏幕觀察者越近。最后才發現這個認識存在很大的問題:
- 首先,
z-index
屬性值並不是在任何元素上都有效果。它僅在定位元素(定義了position
屬性,且屬性值為非static
值的元素)上有效果。 - 判斷元素在
Z軸
上的堆疊順序,不僅僅是直接比較兩個元素的z-index
值的大小,這個堆疊順序實際由元素的層疊上下文、層疊等級共同決定。
要想完全理解一個東西,首先要明白它是什么,也就是它的定義。我們先看看上面提到的層疊上下文
、層疊等級
、層疊順序
都是什么?定義又太過抽象,后面會再用一個具象的比喻來
讓你徹底明白它們到底是什么,有什么聯系。
什么是“層疊上下文”
層疊上下文(stacking context),是HTML中一個三維的概念。在CSS2.1規范中,每個盒模型的位置是三維的,分別是平面畫布上的X軸
,Y軸
以及表示層疊的Z軸
。一般情況下,元素在
頁面上沿X軸Y軸
平鋪,我們察覺不到它們在Z軸
上的層疊關系。而一旦元素發生堆疊,這時就能發現某個元素可能覆蓋了另一個元素或者被另一個元素覆蓋。
如果一個元素含有層疊上下文,(也就是說它是層疊上下文元素),我們可以理解為這個元素在Z軸
上就“高人一等”,最終表現就是它離屏幕觀察者更近。
什么是“層疊等級”
那么,層疊等級指的又是什么?層疊等級(stacking level,叫“層疊級別”/“層疊水平”也行)
- 在同一個層疊上下文中,它描述定義的是該層疊上下文中的層疊上下文元素在
Z軸
上的上下順序。 - 在其他普通元素中,它描述定義的是這些普通元素在
Z軸
上的上下順序。
說到這,可能很多人疑問了,不論在層疊上下文中還是在普通元素中,層疊等級都表示元素在Z軸
上的上下順序,那就直接說它描述定義了所有元素在Z軸
上的上下順序就OK啊!為什么要分開描述?
為了說明原因,先舉個栗子:
再類比回“層疊上下文”和“層疊等級”,就得出一個結論:
- 普通元素的層疊等級優先由其所在的層疊上下文決定。
- 層疊等級的比較只有在當前層疊上下文元素中才有意義。不同層疊上下文中比較層疊等級是沒有意義的。
前面說了那么多,知道了“層疊上下文”和“層疊等級”,其中還有一個最關鍵的問題:到底如何產生層疊上下文呢?如何讓一個元素變成層疊上下文元素呢?
其實,層疊上下文也基本上是有一些特定的CSS屬性創建的,一般有3種方法:
HTML
中的根元素<html></html>
本身j就具有層疊上下文,稱為“根層疊上下文”。- 普通元素設置
position
屬性為非static
值並設置z-index
屬性為具體數值,產生層疊上下文。 - CSS3中的新屬性也可以產生層疊上下文。
position
和
z-index
屬性
<style> div { position: relative; width: 100px; height: 100px; } p { position: absolute; font-size: 20px; width: 100px; height: 100px; } .a { background-color: blue; z-index: 1; } .b { background-color: green; z-index: 2; top: 20px; left: 20px; } .c { background-color: red; z-index: 3; top: -20px; left: 40px; } </style> <body> <div> <p class="a">a</p> <p class="b">b</p> </div> <div> <p class="c">c</p> </div> </body>
z-index
,所以不會產生層疊上下文,所以.a、.b、.c都處於由
<html></html>
標簽產生的“根層疊上下文”中,屬於同一個層疊上下文,此時誰的
z-index
值大,誰在上面。
栗子2: 有兩個div,p.a、p.b被包裹在一個div里,p.c被包裹在另一個盒子里,同時為兩個div和.a、.b、.c設置position
和z-index
屬性
<style> div { width: 100px; height: 100px; position: relative; } .box1 { z-index: 2; } .box2 { z-index: 1; } p { position: absolute; font-size: 20px; width: 100px; height: 100px; } .a { background-color: blue; z-index: 100; } .b { background-color: green; top: 20px; left: 20px; z-index: 200; } .c { background-color: red; top: -20px; left: 40px; z-index: 9999; } </style> <body> <div class="box1"> <p class="a">a</p> <p class="b">b</p> </div> <div class="box2"> <p class="c">c</p> </div> </body>
p.c
元素的
z-index
值為9999,遠大於
p.a
和
p.b
的
z-index
值,但是由於
p.a
、
p.b
的父元素
div.box1
產生的層疊上下文的
z-index
的值為2,
p.c
的父元素
div.box2
所產生的層疊上下
z-index
值為1,所以
p.c
永遠在
p.a
和
p.b
下面。
同時,如果我們只更改p.a
和p.b
的z-index
值,由於這兩個元素都在父元素div.box1
產生的層疊上下文中,所以,誰的z-index
值大,誰在上面。
什么是“層疊順序”
說完“層疊上下文”和“層疊等級”,我們再來說說“層疊順序”。“層疊順序”(stacking order)表示元素發生層疊時按照特定的順序規則在Z軸
上垂直顯示。
由此可見,前面所說的“層疊上下文”和“層疊等級”是一種概念,而這里的“層疊順序”是一種規則。

- 左上角"層疊上下文
background/border
"指的是層疊上下文元素的背景和邊框。 inline/inline-block
元素的層疊順序要高於block
(塊級)/float
(浮動)元素。- 單純考慮層疊順序,
z-index: auto
和z-index: 0
在同一層級,但這兩個屬性值本身是有根本區別的。
inline/inline-block
元素的層疊順序要高於
block
(塊級)/
float
(浮動)元素?這個大家可以思考一下! 其實
border/background
屬於裝飾元素的屬性,浮動和塊級元素一般用來頁面布局,而網頁設計之初最重要的就是文字內容,所以
<style> .box1, .box2 { position: relative; z-index: auto; } .child1 { width: 200px; height: 100px; background: #168bf5; position: absolute; top: 0; left: 0; z-index: 2; } .child2 { width: 100px; height: 200px; background: #32c292; position: absolute; top: 0; left: 0; z-index: 1; } </style> </head> <body> <div class="box1"> <div class="child1"></div> </div> <div class="box2"> <div class="child2"></div> </div> </body>
.box1/.box2
雖然設置了
position: relative
,但是
z-index: auto
的情況下,這兩個
div
還是普通元素,並沒有產生層疊上下文。所以,
child1/.child2
屬於
<html></html>
元素的“根層疊上下文”中,
z-index
值大,誰在上面。
.box1/.box2
的
z-index
屬性值改為
數值0
,其余不變。
.box1, .box2 { position: relative; z-index: 0; }
.box1/.box2
的
z-index
屬性值改為
數值0
,最終結果完全相反。這時
.child2
覆蓋在了
.child1
上面。原因是什么呢?
z-index: 0
后,
.box1/.box2
產生了各自的層疊上下文,這時候要比較
.child1/.child2
的層疊關系完全由父元素
.box1/.box2
的層疊關系
.box1/.box2
的
z-index
值都為
0
,都是塊級元素(所以它們的層疊等級,層疊順序是相同的),這種情況下,在
DOM
結構中
后面的覆蓋前面的,所以
.child2
就在上面。
CSS3中的屬性對層疊上下文的影響
CSS3中出現了很多新屬性,其中一些屬性對層疊上下文也產生了很大的影響。如下:
- 父元素的display屬性值為
flex|inline-flex
,子元素z-index
屬性值不為auto
的時候,子元素為層疊上下文元素; - 元素的
opacity
屬性值不是1
; - 元素的
transform
屬性值不是none
; - 元素
mix-blend-mode屬性值不是
normal`; - 元素的
filter
屬性值不是none
; - 元素的
isolation
屬性值是isolate
; will-change
指定的屬性值為上面任意一個;- 元素的
-webkit-overflow-scrolling
屬性值設置為touch
轉載:https://juejin.im/post/5b876f86518825431079ddd6