一、z-index
z-index用來控制元素重疊時堆疊順序。
适用于:已經定位的元素(即position:relative/absolute/fixed)。
一般了解就是數值越高越靠上,好像很簡單,但是當z-index應用于複雜的HTML元素層次結構,其行為可能很難了解甚至不可預測。因為z-index的堆疊規則很複雜,下面一一道來。
首先解釋一個名詞:
stacking context:翻譯就是“堆疊上下文”。每個元素僅屬于一個堆疊上下文,元素的z-index描述元素在相同堆疊上下文中“z軸”的呈現順序。
z-index取值:
預設值auto:
當頁面新生成一個box時,它預設的z-index值為auto,意味着該box不會自己産生一個新的local stacking context,而是處于和父box相同的堆疊上下文中。
正/負整數
這個整數就是目前box的z-index值。z-index值為0也會生成一個local stacking context,這樣該box父box的z-index就不會和其子box做比較,相當于隔離了父box的z-index和子box的z-index。
接下來從最簡單的不使用z-index的情況開始将,循序漸進。
二、不使用 z-index時堆疊順序
不使用z-index的情況,也是預設的情況,即所有元素都不用z-index時,堆疊順序如下(從下到上)
- 根元素(即HTML元素)的background和borders
- 正常流中非定位後代元素(這些元素順序按照HTML文檔出現順序)
- 已定位後代元素(這些元素順序按照HTML文檔出現順序)
解釋一下後兩條規則:
- 正常流中非positoned element元素,總是先于positioned element元素渲染,是以表現就是在positioned element下方,跟它在HTML中出現的順序無關。
- 沒有指定z-index值的positioned element,他們的堆疊順序取決于在HTML文檔中的順序,越靠後出現的元素,位置越高,和position屬性無關。
例子:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Stacking without z-index</title>
<style type="text/css">
div {
font: 12px Arial;
text-align: center;
}
.bold { font-weight: bold; }
.opacity{opacity: 0.7;}
#normdiv {
height: 70px;
border: 1px dashed #999966;
background-color: #ffffcc;
margin: 0px 50px 0px 50px;
}
#reldiv1 {
height: 100px;
position: relative;
top: 30px;
border: 1px dashed #669966;
background-color: #ccffcc;
margin: 0px 50px 0px 50px;
}
#reldiv2 {
height: 100px;
position: relative;
top: 15px;
left: 20px;
border: 1px dashed #669966;
background-color: #ccffcc;
margin: 0px 50px 0px 50px;
}
#absdiv1 {
position: absolute;
width: 150px;
height: 350px;
top: 10px;
left: 10px;
border: 1px dashed #990000;
background-color: #ffdddd;
}
#absdiv2 {
position: absolute;
width: 150px;
height: 350px;
top: 10px;
right: 10px;
border: 1px dashed #990000;
background-color: #ffdddd;
}
</style>
</head>
<body>
<br /><br />
<div id="absdiv1" class="opacity">
<br /><span class="bold">DIV #1</span>
<br />position: absolute;
</div>
<div id="reldiv1" class="opacity">
<br /><span class="bold">DIV #2</span>
<br />position: relative;
</div>
<div id="reldiv2" class="opacity">
<br /><span class="bold">DIV #3</span>
<br />position: relative;
</div>
<div id="absdiv2" class="opacity">
<br /><span class="bold">DIV #4</span>
<br />position: absolute;
</div>
<div id="normdiv">
<br /><span class="bold">DIV #5</span>
<br />no positioning
</div>
</body>
</html>
View Code
有圖有真相:
分析:
#5沒有定位,處于正常流,是以根據以上規則,先于#1,#2,#3,#4這些已定位元素渲染,在最下方。
#1,#2,#3,#4都是已定位元素,且未設定z-index,是以根據其在文檔中出現的順序依次被渲染,可以去掉apacity檢視清晰效果。
三、浮動堆疊順序
浮動元素z-index位置介于非定位元素和定位元素之間。(從下到上)
- 根元素(即HTML元素)的背景和border
- 浮動元素(浮動元素之間是不會出現z-index重疊的)
- 正常流中inline後代元素
non-positioned元素的背景和邊界沒有被浮動元素影響,但是元素中的内容受影響(浮動布局特性)
舉例:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Stacking and float</title>
<style type="text/css">
div {
font: 12px Arial;
text-align: center;
}
.bold { font-weight: bold; }
.opacity{ opacity: 0.7;}
#absdiv1 {
position: absolute;
width: 150px;
height: 200px;
top: 10px;
right: 140px;
border: 1px dashed #990000;
background-color: #ffdddd;
}
#normdiv {
/* opacity: 0.7; */
height: 100px;
border: 1px dashed #999966;
background-color: #ffffcc;
margin: 0px 10px 0px 10px;
text-align: left;
}
#flodiv1 {
margin: 0px 10px 0px 20px;
float: left;
width: 150px;
height: 200px;
border: 1px dashed #009900;
background-color: #ccffcc;
}
#flodiv2 {
margin: 0px 20px 0px 10px;
float: right;
width: 150px;
height: 200px;
border: 1px dashed #009900;
background-color: #ccffcc;
}
#absdiv2 {
position: absolute;
width: 150px;
height: 100px;
top: 130px;
left: 100px;
border: 1px dashed #990000;
background-color: #ffdddd;
}
</style>
</head>
<body>
<br /><br />
<div id="absdiv1" class="opacity">
<br /><span class="bold">DIV #1</span>
<br />position: absolute;
</div>
<div id="flodiv1" class="opacity">
<br /><span class="bold">DIV #2</span>
<br />float: left;
</div>
<div id="flodiv2" class="opacity">
<br /><span class="bold">DIV #3</span>
<br />float: right;
</div>
<br />
<div id="normdiv">
<br /><span class="bold">DIV #4</span>
<br />no positioning
</div>
<div id="absdiv2" class="opacity">
<br /><span class="bold">DIV #5</span>
<br />position: absolute;
</div>
</body>
</html>
分析:
#4是正常流中非定位的元素,是以先被渲染,在最底層。
#2 #3一個左浮動,一個右浮動,接着被渲染。彼此不會因為z-index值被覆寫。見下圖。
#1 #5為已定位的元素,最後被渲染,當浏覽器視窗變小時,#5在#1上面,因為HTML文檔中#5在#1後面。見下圖。
四、z-index
預設的堆疊順序上面說了,要想改變 元素的堆疊順序就得用到z-index。
Note:前兩種情況中,雖然有元素之間的重疊覆寫,但是它們都是處在同一個z-layer的。因為沒有設定z-index屬性,預設的渲染層就是layer 0。是以要注意,不同層中元素之間覆寫是理所當然的,但是同一層中的元素也會發生覆寫。
z-index隻适用于已經定位的元素(即position:relative/absolute/fixed)。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Stacking without z-index</title>
<style type="text/css">
div {
font: 12px Arial;
text-align: center;
opacity: 0.7;
}
.bold { font-weight: bold; }
#normdiv {
z-index: 8;
height: 70px;
border: 1px dashed #999966;
background-color: #ffffcc;
margin: 0px 50px 0px 50px;
}
#reldiv1 {
z-index: 3;
height: 100px;
position: relative;
top: 30px;
border: 1px dashed #669966;
background-color: #ccffcc;
margin: 0px 50px 0px 50px;
}
#reldiv2 {
z-index: 2;
height: 100px;
position: relative;
top: 15px;
left: 20px;
border: 1px dashed #669966;
background-color: #ccffcc;
margin: 0px 50px 0px 50px;
}
#absdiv1 {
z-index: 5;
position: absolute;
width: 150px;
height: 350px;
top: 10px;
left: 10px;
border: 1px dashed #990000;
background-color: #ffdddd;
}
#absdiv2 {
z-index: 1;
position: absolute;
width: 150px;
height: 350px;
top: 10px;
right: 10px;
border: 1px dashed #990000;
background-color: #ffdddd;
}
</style>
</head>
<body>
<br /><br />
<div id="absdiv1">
<br /><span class="bold">DIV #1</span>
<br />position: absolute;
<br />z-index: 5;
</div>
<div id="reldiv1">
<br /><span class="bold">DIV #2</span>
<br />position: relative;
<br />z-index: 3;
</div>
<div id="reldiv2">
<br /><span class="bold">DIV #3</span>
<br />position: relative;
<br />z-index: 2;
</div>
<div id="absdiv2">
<br /><span class="bold">DIV #4</span>
<br />position: absolute;
<br />z-index: 1;
</div>
<div id="normdiv">
<br /><span class="bold">DIV #5</span>
<br />no positioning
<br />z-index: 8;
</div>
</body>
</html>
五、stacking context
為什麼上個例子中元素的堆疊順序受z-index的影響呢?因為這些元素有些特殊的屬性觸發它們生存堆疊上下文(stacking context)。
問題來了,什麼樣的元素會生成堆疊上下文呢?符合下面規則之一的:
- 根元素(即HTML元素)
- 已定位元素(即絕對定位或相對定位)并且z-index不是預設的auto。
- a flex item with a z-index value other than "auto",
- 元素opacity屬性不為1(See the specification for opacity)
- 元素transform不為none
- 元素min-blend-mode不為normal
- 元素filter屬性不為none
- 元素isolation屬性為isolate
- on mobile WebKit and Chrome 22+,
always creates a new stacking context, even when z-index is "auto" (See this post)position: fixed
- specifing any attribute above in
even you don't write themselves directly (See this post)will-change
- elements with
set to "touch"-webkit-overflow-scrolling
在堆疊上下文(stacking context)中 ,子元素的堆疊順序還是按照上述規則。重點是,子元素的z-index值隻在父元素範圍内有效。子堆疊上下文被看做是父堆疊上下文中一個獨立的子產品,相鄰的堆疊上下文完全沒關系。
總結幾句:
渲染的時候,先确定小的stacking context中的順序,一個小的stacking context确定了以後再将其放在父stacking context中堆疊。有種由内而外,由小及大的感覺。
舉例:HTML結果如下,最外層是HTML元素,包含#1 #2 #3,#3中又包含着#4,#5,#6。
Root(HTML)
- DIV #1
- DIV #2
- DIV #3
- DIV #4
- DIV #5
- DIV #6

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Understanding CSS z-index: The Stacking Context: Example Source</title>
<style type="text/css">
* {
margin: 0;
}
html {
padding: 20px;
font: 12px/20px Arial, sans-serif;
}
div {
opacity: 0.7;
position: relative;
}
h1 {
font: inherit;
font-weight: bold;
}
#div1, #div2 {
border: 1px solid #696;
padding: 10px;
background-color: #cfc;
}
#div1 {
z-index: 5;
margin-bottom: 190px;
}
#div2 {
z-index: 2;
}
#div3 {
z-index: 4;
opacity: 1;
position: absolute;
top: 40px;
left: 180px;
width: 330px;
border: 1px solid #900;
background-color: #fdd;
padding: 40px 20px 20px;
}
#div4, #div5 {
border: 1px solid #996;
background-color: #ffc;
}
#div4 {
z-index: 6;
margin-bottom: 15px;
padding: 25px 10px 5px;
}
#div5 {
z-index: 1;
margin-top: 15px;
padding: 5px 10px;
}
#div6 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
width: 150px;
height: 125px;
border: 1px solid #009;
padding-top: 125px;
background-color: #ddf;
text-align: center;
}
</style>
</head>
<body>
<div id="div1">
<h1>Division Element #1</h1>
<code>position: relative;<br/>
z-index: 5;</code>
</div>
<div id="div2">
<h1>Division Element #2</h1>
<code>position: relative;<br/>
z-index: 2;</code>
</div>
<div id="div3">
<div id="div4">
<h1>Division Element #4</h1>
<code>position: relative;<br/>
z-index: 6;</code>
</div>
<h1>Division Element #3</h1>
<code>position: absolute;<br/>
z-index: 4;</code>
<div id="div5">
<h1>Division Element #5</h1>
<code>position: relative;<br/>
z-index: 1;</code>
</div>
<div id="div6">
<h1>Division Element #6</h1>
<code>position: absolute;<br/>
z-index: 3;</code>
</div>
</div>
</body>
</html>
效果:
分析一下:
1、因為設定了div {opacity: 0.7; position: relative;},是以#1~#6的z-index都是有效的。
2、為什麼#4的z-index比#1高,但是卻在#1下面?因為#4的z-index雖然值大,但它的作用域在包含塊#3内,而#1的z-index的作用域在html内,和#3同屬html,而#3的z-index小于#1。
3、為什麼#2的z-index值比#5的大,還在下面?同上。
4、#3的z-index是4,但該值和#4,#5,#6的z-index不具有可比性,它們不在一個上下文環境。
5、如何輕易的判斷兩個元素的堆疊順序?
z-index對堆疊順序的控制類似于排版時候一大章下幾個小節的樣子,或者版本号中一個大的版本号跟着小版本号。
Root-z-index值為預設auto,即0
- DIV #2 - z-index 值為2
- DIV #3 - z-index 值為4
- DIV #5 - z-index值為 1,其父元素z-index值 4,是以最終值為4.1
- DIV #6 - z-index值為 3,其父元素z-index值 4,是以最終值為4.3
- DIV #4 - z-index值為 6,其父元素z-index值 4,是以最終值為4.6
- DIV #1 - z-index 值為5
想看更多例子,可參考文章最後的資源連結。
六、 合理使用z-index數值
如果現有三個堆疊的層,從上到下分别為:DIV3,DIV2,DIV1,設定時以100為間隔,設定DIV1的z-index為0,DIV2的z-index為100,設定DIV3的z-index為200。這樣後期如果需要在DIV1和DIV2之間加入一些層的話,以10為間隔,設定z-index為10,20等。再需要向z-index0和z-index10之間加入一層的話以5為間隔。這樣的寫法可以友善後期擴充添加内容。
盡量避免給z-index使用負值。當然不是絕對的,比如在做圖文替換的時候可以使用負值。
七、資源連結
MDN z-index
understanding css z-index
- Stacking without z-index : Default stacking rules
- Stacking and float : How floating elements are handled
- Adding z-index : Using z-index to change default stacking
- The stacking context : Notes on the stacking context
- Stacking context example 1 : 2-level HTML hierarchy, z-index on the last level
- Stacking context example 2 : 2-level HTML hierarchy, z-index on all levels
- Stacking context example 3 : 3-level HTML hierarchy, z-index on the second level
w3c z-index
本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章内容也不定時更新,為避免誤導讀者,友善追根溯源,請諸位轉載注明出處:http://www.cnblogs.com/starof/p/4424926.html有問題歡迎與我讨論,共同進步。
如果覺得本文對您有幫助~可以支付寶(左)或微信支援一下:
看到小夥伴打賞時給我寫一些鼓勵的話,真的非常感動,謝謝你們。
我開了個微信公衆号(第三個二維碼)用來分享自己的職場英語相關學習經驗,感興趣可以關注,我會不斷更新~