1. 堆疊順序
堆疊順序(stacking order):HTML 內(nèi)元素發(fā)生層疊的時(shí)候的特定垂直順序,即元素在用戶(hù)視線(xiàn)方向上的順序。
一般而言,div 以?xún)?nèi)在層疊順序上對(duì)于視覺(jué)有影響的一般有以下幾個(gè):
- background
- border
- 塊級(jí)元素
- 內(nèi)聯(lián)元素
- 浮動(dòng)塊級(jí)元素
- 定位塊級(jí)元素
接下來(lái),我們一個(gè)一個(gè)來(lái)測(cè)試一下他們的堆疊順序。
1. 首先,測(cè)試一下 background 和 border 的堆疊順序。
在日常寫(xiě)頁(yè)面中,很大可能是這樣的:
HTML
<body>
<div class="parent"></div>
</body>
CSS
.parent{
height:40px;
border:10px solid rgba(255,0,0,1);
background:#000;
}

一個(gè) div 元素內(nèi)有一個(gè) background 和一個(gè) border,它們兩者是分開(kāi)的嗎?
現(xiàn)在,將該 div 的 border 顏色改為半透明
.parent{
height:40px;
border:10px solid rgba(255,0,0,0.4);
background:#000;
}

從頁(yè)面效果,可以很明顯地看出來(lái),border 的顏色并不是純種的紅色,而是紅色之中透著黑色。
顯而易見(jiàn),border 之中的黑色就是 div 元素的background。
由上面可以推斷得出,border 的堆疊順序是比 background 要高的。即 border > background
2. 接下來(lái),給 div 加一個(gè)內(nèi)聯(lián)元素和一個(gè)塊級(jí)元素
HTML
<body>
<div class="parent">
<span>內(nèi)聯(lián)元素</span>
<div class="child"></div>
</div>
</body>
CSS
.parent{
height:150px;
border:10px solid rgba(255,0,0,1);
background:#000;
}
span{
color:#fff;
}
.child{
width:80px;
height:50px;
background:green;
}
顯示效果

從上圖可以看出來(lái),內(nèi)聯(lián)元素和塊級(jí)元素的堆疊順序都是大于 background 的,那么他們與 border 相比較呢?
想辦法把這兩個(gè)元素移動(dòng)到與 border 相覆蓋,就可以知道他們的堆疊順序。
往兩個(gè)元素上分別加一個(gè) margin-left:-10px;
CSS
.parent{
height:150px;
border:10px solid rgba(255,0,0,1);
background:#000;
}
span{
color:#fff;
margin-left:-10px;
}
.child{
width:80px;
height:50px;
background:green;
margin-left:-10px;
}
顯示效果

可以知道,內(nèi)聯(lián)元素和塊級(jí)元素的堆疊順序都大于 border 的堆疊順序。那么這兩者之間的堆疊順序呢?
再往塊級(jí)元素上加一個(gè) margin-top:-10px;
CSS
.parent{
height:150px;
border:10px solid rgba(255,0,0,1);
background:#000;
}
span{
color:#fff;
margin-left:-10px;
}
.child{
width:80px;
height:50px;
background:green;
margin-left:-10px;
margin-top:-10px;
}
顯示效果

從上圖可以看到,綠色背景的塊級(jí)元素向上移動(dòng) 10px,但是內(nèi)聯(lián)元素依然在塊級(jí)元素上面,說(shuō)明內(nèi)聯(lián)元素的堆疊順序大于塊級(jí)元素的內(nèi)聯(lián)順序,即 內(nèi)聯(lián)元素 > 塊級(jí)元素 > border > background。
3. 接下來(lái)該比較一下浮動(dòng)元素了
先加一個(gè)浮動(dòng)元素,背景色為藍(lán)色。
HTML
<body>
<div class="parent">
<span>內(nèi)聯(lián)元素</span>
<div class="child"></div>
<div class="float"></div>
</div>
</body>
CSS
.float{
width:80px;
height:50px;
background:blue;
float:left;
}
顯示效果

現(xiàn)在,先測(cè)試一次,藍(lán)色的浮動(dòng)元素與目前已知的最高級(jí)的內(nèi)聯(lián)元素哪個(gè)堆疊順序比較大。給浮動(dòng)元素加一個(gè)margin-top:-60px;
.float{
width:80px;
height:50px;
background:blue;
float:left;
margin-top: -60px;
}

由上圖可以知道,內(nèi)聯(lián)元素在浮動(dòng)元素上面,所以?xún)?nèi)聯(lián)元素的堆疊順序比浮動(dòng)元素大,而浮動(dòng)元素又在塊級(jí)元素上面,所以浮動(dòng)元素的堆疊順序大于塊級(jí)元素。即 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > border > background。
4. 接下來(lái)是定位(position:relative;和position:absolute;)元素
依然是加一個(gè)定位元素
HTML
<body>
<div class="parent">
<span>內(nèi)聯(lián)元素</span>
<div class="child"></div>
<div class="float"></div>
<div class="relative"></div>
</div>
</body>
CSS
.relative{
width:70px;
height:50px;
background:yellow;
position:relative;
}
顯示效果

依然是加margin-top:-50px;
.relative{
width:70px;
height:50px;
background:yellow;
position:relative;
margin-top:-50px;
}

可以看到,position:relative; 的元素直接蓋住了目前已知最高等級(jí)的內(nèi)聯(lián)元素,說(shuō)明 position:relative; 的元素的堆疊順序比內(nèi)聯(lián)元素的要大。
接下來(lái)看一下 position:absolute; 將上面 position:relative; 改為 position:absolute;
.relative{
width:70px;
height:50px;
background:yellow;
position:absolute;
margin-top:-50px;
}

從圖片可以看出結(jié)果是一摸一樣的,說(shuō)明 position:relative和 position:absolute; 有一樣的堆疊順序。
所以:定位元素 > 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > border > background
5. 最后是 z-index 的影響
首先要知道,z-index 生效的前提是該元素是 position 屬性值是非static的元素,此時(shí)的 z-index為 auto。再添加一個(gè)元素,使它的 z-index生效
HTML
<body>
<div class="parent">
<span>內(nèi)聯(lián)元素</span>
<div class="child"></div>
<div class="float"></div>
<div class="relative"></div>
<div class="z-index"></div>
</div>
</body>
CSS
.z-index{
width:90px;
height:50px;
background:orange;
position:absolute;
z-index:1;
}
顯示效果

接下來(lái),繼續(xù)給一個(gè)margin-top:-40px;
.z-index{
width:90px;
height:50px;
background:orange;
position:absolute;
z-index:1;
margin-top: -40px;
}

可以看到橙色的加了 z-index 的元素蓋住了定位元素,說(shuō)明: 正z-index > 定位元素 > 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > border > background。
現(xiàn)在測(cè)試一下負(fù)z-index,將z-index:1;改為 z-index:-1;
.z-index{
width:90px;
height:50px;
background:orange;
position:absolute;
z-index:-1;
margin-top:-40px;
}

可以看到,橙色元素完全被蓋住了。
修改一下margin,試著讓它顯示出來(lái)。
.z-index{
width:90px;
height:50px;
background:orange;
position:absolute;
z-index:-1;
margin-top:0px;
}

可以看到,即使不加margin負(fù)值,依然看不到。
設(shè)置margin-top:70px;
.z-index{
width:90px;
height:50px;
background:orange;
position:absolute;
z-index:-1;
margin-top:70px;
}

可以看到,橙色有一部分被背景蓋住了,說(shuō)明:
正z-index > 浮動(dòng)元素 > 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > border > background > 負(fù)z-index
綜合上面所有內(nèi)容,元素的堆疊順序就出來(lái)了。
就是下面這個(gè):
正z-index > 浮動(dòng)元素 > 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > border > background > 負(fù)z-index
上面的順序,越大的離用戶(hù)越近。
2. 堆疊上下文
堆疊上下文:stacking context,類(lèi)似與作用域,由不同的CSS屬性造成的一類(lèi)具有相同特征的東西,并沒(méi)有特定的概念。堆疊上下文影響的是元素 CSS 屬性中的 z-index,父元素是否是堆疊上下文,對(duì)具有z-index屬性的子元素的堆疊順序有影響。
文檔中的層疊上下文由滿(mǎn)足以下任意一個(gè)條件的元素形成:
- 根元素 (HTML),
- z-index 值不為 "auto"的 絕對(duì)/相對(duì)定位,
- 一個(gè) z-index 值不為 "auto"的 flex 項(xiàng)目 (flex item),即:父元素 display: flex|inline-flex的元素
- opacity 屬性值小于 1 的元素(參考 the specification for opacity),
- transform 屬性值不為 "none"的元素,
- mix-blend-mode 屬性值不為 "normal"的元素,
- filter值不為“none”的元素,
- perspective值不為“none”的元素,
- isolation 屬性被設(shè)置為 "isolate"的元素,
- position: fixed
- 在 will-change 中指定了任意 CSS 屬性,即便你沒(méi)有直接指定這些屬性的值(參考 這篇文章)
- -webkit-overflow-scrolling 屬性被設(shè)置 "touch"的元素
接下來(lái)看一下堆疊上下文對(duì) z-index 的影響:
首先創(chuàng)建一個(gè)父元素的 div 作為容器,然后添加兩個(gè)子 div ,兩個(gè)子 div 里分別添加一個(gè)子 div
HTML
<body>
<div class="parent">
<div class="a relative">
<div class="aaa">aaa</div>
</div>
<div class="b relative">
<div class="bbb">bbb</div>
</div>
</div>
</body>
接下來(lái),使用 CSS 添加樣式,此時(shí)頁(yè)面內(nèi)有一個(gè)堆疊上下文=》html 元素
CSS
.parent{
height:200px;
border:10px solid red;
background:black;
padding:10px;
}
.a,.b{
border:1px solid red;
width:200px;
height:100px;
background:green;
}
.aaa,.bbb{
background:yellow;
}
.relative{
position:relative;
}
顯示效果

接下來(lái)給 bbb 添加一個(gè) z-index:1;并使它移動(dòng)到 aaa 的位置。
.bbb{
z-index:1;
margin-top:-90px;
}

可以看到 bbb 蓋住了 aaa ,因?yàn)?bbb 的 z-index:1; 比 aaa 默認(rèn)的 z-index:auto;更靠近用戶(hù)。說(shuō)明 在同一個(gè)堆疊上下文中,z-index大的比z-index小的更靠近用戶(hù)
接下來(lái)使 a 和 b 形成堆疊上下文
.a,.b{
border:1px solid red;
width:200px;
height:100px;
background:green;
z-index:0;
}

頁(yè)面并沒(méi)有變化,那么這時(shí)候修改一下 aaa 和 bbb 的z-index 大小呢?將 aaa 的 z-index 改為2
.aaa{
z-index:2;
}

頁(yè)面依然沒(méi)有變化,說(shuō)明不同堆疊上下文中,z-index的大小不會(huì)影響到元素的堆疊順序,此時(shí)的堆疊順序與堆疊上下文所屬元素的堆疊順序有關(guān)。
接下來(lái)讓 parent 元素形成堆疊上下文,并給 a 和 b 一個(gè)負(fù)z-index
.parent{
height:200px;
border:10px solid red;
background:black;
padding:10px;
position:relative;
z-index:0;
}
.a,.b{
border:1px solid red;
width:200px;
height:100px;
background:green;
}
.aaa,.bbb{
background:yellow;
}
.relative{
position:relative;
z-index:-1;
margin-top:50px;
}

可以看到,a 和 b 蓋住了 border,說(shuō)明堆疊上下文中,負(fù)z-index > border。可以看作是堆疊上下文將所有元素包裹了起來(lái),不允許有比堆疊上下文低的堆疊順序。
3. 總結(jié)
- 普通塊級(jí)元素中,z軸元素的堆疊順序如下:
正z-index > 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > border > background >負(fù)z-index - 堆疊上下文中,z軸元素的堆疊順序如下:
正z-index > 內(nèi)聯(lián)元素 > 浮動(dòng)元素 > 塊級(jí)元素 > 負(fù)z-index > border > background - z軸順序遵循兩個(gè)原則:
- 誰(shuí)大誰(shuí)上
- 大小一樣,后來(lái)居上
部分參考自: