z-index和層疊上下文

z-index基礎介紹:
三維座標空間裏,x軸一般用來表示水平位置,y軸來表示垂直位置,還有z軸來表示在紙面內外方向上的位置,像下面的圖片同樣:css

clipboard.png

css容許的z-index的值是
● auto (自動,默認值)
● (整數)
● inherit (繼承)
當設置成整數時,值越大越靠近用戶。
若是有兩個元素放在了一塊兒,佔據了一塊共同的區域,那麼有着較大z-index值的元素就會掩蓋有着較低z-index值的元素在共同區域的那一部分。html

關於z-index的三個思考
● 當一個設置了z-index值的定位元素與正常的文檔流中的元素相互重疊的時候,誰會被置於上方?
● 當定位元素與浮動元素相互重疊的時候,誰會被置於上方?
● z-index必需要與定位一塊兒使用纔會生效嗎?
● z-index大的元素必定會遮擋z-index小的元素嗎?
解決上面的問題須要深刻理解z-index的原理,須要知道層疊上下文和層疊順序。css3

層疊上下文的概念:
層疊上下文就是html中的一個三維概念。至關於在水平面建立了一個z軸,有了層疊上下文的元素會離用戶更近。它包含了一組層疊層的元素。咱們所建立的每個網頁都有一個默認的層疊上下文,層疊上下文的根就是html,其餘的全部元素都會在這個層疊上下文佔據一個層疊水平,或高或低。web

層疊順序:
層疊順序:這是一種規則,表示元素髮生重疊時,在z軸上的顯示順序。
在一個層疊上下文中,有七種層疊順序:瀏覽器

clipboard.png

(1) 背景和邊框:創建層疊上下文的元素的背景和邊框,層疊中的最低級別
(2) 負的z-index:z-index 爲負值時造成的層疊上下文
(3) 塊級盒子: 文檔流中正常的塊級元素
(4) 浮動盒子:非定位的浮動盒子
(5) 行內盒:文檔流內的行內級盒子
(6) z-index:0 定位元素,這些元素創建了新的層疊上下文。
(7) 正的z-index:層疊中的最高級別。佈局

頁面中內聯元素的層疊順序要比浮動元素和塊狀元素都高的緣由,浮動和塊級盒子主要用來佈局,而內聯的元素用來顯示頁面內容。因此比起他的要高。flex

ps: 圖上缺乏的信息
inline和inline-block是一個同一個level
z-index:0實際上和z-index:auto單純從層疊水平上看,是能夠當作是同樣的。spa

層疊順序規則
誰大誰上:當具備明顯的層疊水平標示的時候,好比說z-index值,在同一個層疊上下文領域,層疊水平值大的那一個覆蓋小的那一個
後來居上:當元素的層疊水平一致、層疊順序相同的時候,在DOM流中處於後面的元素會覆蓋前面的元素。3d

層疊上下文元素的特性
● 層疊上下文的層疊水平要比普通元素高;
● 層疊上下文能夠嵌套,內部層疊上下文及其全部子元素均受制於外部的層疊上下文。
● 每一個層疊上下文不會影響它的兄弟元素,當進行層疊變化或渲染的時,只和該元素的後代元素有關。
● 每一個層疊上下文是獨立的,當元素髮生層疊的時,它的層疊順序依賴在父層疊上下文的層疊順序中。code

層疊上下文的建立
(1)根層疊上下文:
指的是頁面根元素,也就是html元素。這就是爲何,絕對定位元素在left/top等值定位的時候,若是沒有其餘定位元素影響,會相對瀏覽器窗口定位的緣由。
(2)定位元素
含有position的值是relative或absolute的定位元素,以及FireFox/IE瀏覽器(Chrome等webkit內核瀏覽器是fixed的自動造成層疊上下文,無需將z-index設置成數值)下含有position:fixed的定位元素,當其z-index值不是auto的時候,會建立層疊上下文。
demo:
(1)

<div style="position:relative; z-index:auto;">
    <img src="./cat.jpg" style="position:absolute; z-index:2;" class="cat"> 
</div>

<div style="position:relative; z-index:auto;">
   <img src="./dog.jpg" style="position:relative; z-index:1;" class="dog"> 
</div>

結果:

clipboard.png

(2)

<div style="position:relative; z-index:0;">
    <img src="./cat.jpg" style="position:absolute; z-index:2;" class="cat"> 
</div>
<div style="position:relative; z-index:0;">
    <img src="./dog.jpg" style="position:relative; z-index:1;" class="dog"> 
</div>

結果:

clipboard.png

緣由:
z-index 值是auto,是一個普通元素,兩個img層比較不受父級的影響,按照規則誰大誰上,因而,z-index爲2的貓覆蓋值爲1的狗
z-index:0會建立一個層疊上下文。此時,層疊規則就發生了變化。層疊上下文特性裏最後一條規則,每一個層疊上下文都是獨立的。兩個img的層疊順序比較變成了優先比較其父級層疊上下文元素的層疊順序。因爲二者都是z-index:0,同樣大,此時,遵循層疊規則後來居上,根據在DOM出現的前後順序決定誰在上面,因而,位於後面的狗覆蓋貓。此時img元素上的z-index是沒有任何意義的。

E6/IE7瀏覽器有個bug,就是z-index:auto的定位元素也會建立層疊上下文。

(3) CSS3下的層疊上下文
CSS3的一些新屬性,會建立局部的層疊上下文,而且transform屬性會改變絕對定位的字元素的包含塊。
如下幾種狀況會產生新的層疊上下文:
1.z-index值不爲auto的flex項(父元素display:flex|inline-flex).
2.元素的opacity值不是1.
3.元素的transform值不是none.
4.元素mix-blend-mode值不是normal.
5.元素的filter值不是none.
6.元素的isolation值是isolate.
7.will-change指定的屬性值爲上面任意一個。
8.元素的-webkit-overflow-scrolling設爲touch.

display:flex|inline-flex與層疊上下文
須要知足兩個條件才能造成層疊上下文:
(1) 父級須要是display:flex/inline-flex
(2) 子元素的z-index不是auto,必須是數值。
此時,這個子元素爲層疊上下文元素,沒錯,注意了,是子元素,不是flex父級元素
demo:

<div class="box">
    <div>
        <img src="./dog.jpg" class="dog">
    </div>
</div>

.box div {
    width: 300px;
    height: 300px;
    background-color: pink;
    z-index: 101;
}
.box div img {
    width: 400px;
    height: 200px;
    position: relative;
    z-index: -1;
}

結果:

clipboard.png

緣由:此時的div是一個普通的元素,它上面設置的z-index是無效的,img的負值z-index會被塊級元素所遮擋。

接上:

.box {
    display: flex;
}

結果:

clipboard.png

div加上flex值以後,此時的z-index就會生效,會使它的子元素既內部的div造成層疊上下文。根據7層的層疊順序,background的那層會被負的z-index的那層所遮擋。
flex的出現打破了傳統的z-index必須與定位的元素一塊兒使用纔會生效的觀念。

opacity與層疊上下文

<div>
    <img src="./dog.jpg" class="dog">
</div>

div {
    width: 300px;
    height: 300px;
    background-color: pink;
}
div img {
    width: 400px;
    height: 200px;
    position: relative;
    z-index: -1;
}

結果:

clipboard.png

給div加一個opacity的屬性:

div {
    width: 300px;
    height: 300px;
    background-color: pink;
    opacity: 0.5; /* 添加opcity屬性 */
}

只要設置的opacity的值不是1,就會造成層疊上下文。
表現結果:

clipboard.png

transform對層疊上下文的影響
同上,對外層的div設置transform: rotate(15deg),會造成層疊上下文,致使圖片顯示在div的上面。

transform除了創建局部的層疊上下文還會改變絕對定位(固定定位也是絕對定位的一種)子元素的包含塊,
包含塊的概念:一些盒子根據它外面的矩形盒子計算獲得自身的定位和大小,這個外層的矩形盒子就是包含塊。

對固定定位的元素的影響
正常的固定定位的包含塊是視口,加了transform就不同了

<div id="transform">
    <div id="fixed"></div>
</div>
    
div {
    width: 100px;
    height: 100px;
}
#fixed {
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background: blue;
}
#transform {
    background: red;
    padding: 20px;
}

fixed將會鋪滿整個屏幕。
結果:
clipboard.png

上面加上

#transform {
    transform: scale(1);
}

結果:

clipboard.png

緣由,fixed的包含塊再也不是視口,而是transform這個div最邊緣。因此fixed的寬高均爲140px

對絕對定位的元素的影響:

<div id="relative">
    <div id="transform">
        <div id="absolute"></div>
    </div>
</div>

#relative {
    position: relative;
    width: 100px;
    height: 100px;
    background: green;
}
#absolute {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background: blue;
}
#transform {
    background: red;
    width: 50px;
    height: 50px;
}

此時absolute的包含塊爲relative的內邊距盒的邊緣盒。因此absolute的寬高是100px
給transform div加上transform屬性

結果:

clipboard.png

因爲transform建立了局部層疊上下文,absolute的包含塊再也不是 relative而是transform了,根據這一新的包含塊,得新寬和高爲50px。
只要是有了transform這個屬性不論它的值是什麼都會影響絕對定位的子包含塊。

總結 :
層疊上下文的元素的層疊順序在哪一層:
依賴z-index值的元素,根據z-index的值來決定。
不依賴z-index的值的元素,它們的z-index的auto值至關於z-index:0級別。

第二種狀況解釋了爲何定位的元素會覆蓋掉普通流中的元素。定位的元素,會默認加上z-index: auto,按照7種層疊順序,會遮蓋普通流的元素。

當z-index的值同是auto,就是說層疊上下文的元素和定位的元素處於同一個層疊順序時,當她們發生重疊時,後面的元素會遮蓋上面的元素:

<img src="./dog.jpg" style="opacity: 0.5" class="dog"> 
<img src="./cat.jpg" style="position:relative; margin-left:-100px;" class="cat">

clipboard.png

上面的元素調換位置:

<img src="./cat.jpg" style="position:relative; margin-left:-100px;" class="cat"> 
<img src="./dog.jpg" style="opacity: 0.5" class="dog">

clipboard.png

z-index本質上仍是誰大誰在上面,雖然css3新加的一些屬性使z-index變的複雜,最多見的影響可能就是flex佈局致使的,可是規則仍是按照7種層疊順序來排布。

相關文章
相關標籤/搜索