對於stacking context,在MDN中的描述是css
Stacking context is the three-dimensional conceptualization of HTML
elements along an imaginary z-axis relative to the user who is assumed
to be facing the viewport or the webpage.HTML elements occupy this
space in priority order based on element attributes.html
翻譯過來是:
層疊上下文是HTML元素的三維概念,這些HTML元素在一條假想的相對於面向(電腦屏幕的)視窗或者網頁的用戶的 z 軸上延伸,HTML 元素依據其自身屬性按照優先級順序佔用層疊上下文的空間。
z軸即用戶與屏幕間看不見的垂直線。web
層疊水平順序決定了同一個層疊上下文中元素在z軸上的顯示順序ide
關於這個,有一張圖形能夠形象的說明wordpress
不過上面圖示的說法有一些不許確,按照 W3官方 的說法,準確的 7 層爲:佈局
the background and borders of the element forming the stacking context.flex
the child stacking contexts with negative stack levels (most negative first).ui
the in-flow, non-inline-level, non-positioned descendants.this
the non-positioned floats.spa
the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
the child stacking contexts with positive stack levels (least positive first).
翻譯過來是:
造成層疊上下文環境的元素的背景與邊框
擁有負 z-index 的子堆疊上下文元素 (負的越高越堆疊層級越低)
正常流式佈局,非 inline-block,無 position 定位(static除外)的子元素
無 position 定位(static除外)的 float 浮動元素
正常流式佈局, inline-block元素,無 position 定位(static除外)的子元素(包括 display:table 和 display:inline )
擁有 z-index:0 的子堆疊上下文元素
擁有正 z-index: 的子堆疊上下文元素(正的越低越堆疊層級越低)
一個普通元素具備了層疊上下文,其層疊順序就會變高。那它的層疊順序究竟在哪一個位置呢?
這裏須要分兩種狀況討論:
若是層疊上下文元素不依賴z-index數值,則其層疊順序是z-index:auto可當作z:index:0級別;
若是層疊上下文元素依賴z-index數值,則其層疊順序由z-index值決定。
因此爲何定位元素會層疊在普通元素的上面?其根本緣由就在於,元素一旦成爲定位元素,其z-index就會自動生效,此時其z-index就是默認的auto,也就是0級別,根據上面的層疊順序表,就會覆蓋inline或block或float元素。
而不支持z-index的層疊上下文元素自然z-index:auto級別
,也就意味着,層疊上下文元素和未設置z-index的定位元素是一個層疊順序的,因而當他們發生層疊的時候,遵循的是「後來居上」準則。
層疊上下文能夠嵌套,內部層疊上下文及其全部子元素均受制於外部的層疊上下文。
在同一個層疊上下文中,則根據7階層疊水平比較。若兩元素在同一層疊水平,則後來居上,即在DOM流中處於後面的元素會覆蓋前面的元素。
在不一樣的層疊上下文中,則直接比較父元素的層疊水平:
若父元素的z-index不一樣,則z-index數值越大,越在上面。
若父元素的z-index相同,則在DOM流中處於後面的元素會覆蓋前面的元素。
注:
比較時,先看兩個元素是否是在同一個父元素之下,若不是,則一層層往上找,直到找到其祖先元素在同一級時中止。而後,再依次往下尋找各自的子元素,找到第一個是層疊上下文元素的子元素後進行比較。
子元素的 z-index 值只在父級層疊上下文中有意義。即父元素的 z-index 低於父元素另外一個同級元素,子元素 z-index再高也沒用。
例:
<body> <div class="div1"> <div class="div1-1"> <div class="div1-1-1">div1-1-1</div> </div> </div> <div class="div2"> <div class="div2-1"> <div class="div2-1-1">div2-1-1</div> </div> </div> </body>
當css按如下設置,則出現紅色在綠色之上的效果。
緣由:要比較div-1-1與div2-1-1的上下,則先找到div1與div2在同一層級。而div1爲普通元素,div1-1爲層疊上下文元素,div2爲層疊上下文元素,因此這時候div2與div1,div1-1在同一 個層疊上下文,而div1-1的z-index爲1,div2的z-index爲1,DOM流中div2在div1-1以後,因此紅色在綠色之上。若此時將div1-1的z-index設置爲2時,則會出現綠色在紅色之上的效果。
.div2 { position: absolute; z-index: 1; } .div1-1 { position: absolute; z-index: 1; } .div2-1 { position: absolute; z-index: 2; } .div1-1-1 { background-color: rgba(20, 150, 150, 0.9); width: 100px; height: 100px; line-height: 100px; text-align: center; border: 1px dashed #e6e6e6; font-size: 16px; position: absolute; z-index: 2; } .div2-1-1 { background-color: rgba(233, 2, 233, 0.5); width: 100px; height: 100px; margin-left: 70px; line-height: 100px; text-align: center; border: 1px dashed #e6e6e6; font-size: 16px; position: absolute; z-index: 3; }
當在原樣式基礎上,再添加一個樣式,則出現綠色在紅色之上的效果,是由於這時候div2與div1在同一個層疊上下文,而div1的z-index爲2,div2的z-index爲1,因此綠色在紅色之上。
.div1 { position: absolute; z-index: 2; }
補充:
如下例子中,當將鼠標放在d1-inner上時,會發現d2在d1-inner上面。
緣由:不支持z-index的層疊上下文元素自然z-index:auto
級別,因此當給d1-inner添加transform: scale(1.7,1.7);
時,d1-inner在根元素的層疊上下文中的z-index:auto級別,而d2未設置z-index,因此其z-index就是默認的auto。二者都在根元素的層疊上下文中的z-index:auto級別,那就根據後來居上判斷。d1-inner的父元素d1在DOM流中在d2的前面,因此致使d2在d1-inner上面。
<style type="text/css"> .d1-inner { background-color: green; height: 150px; width: 400px; font-size: 40px; line-height: 1; color: red; } .d1-inner:hover { transform: scale(1.7, 1.7); } .d2 { position: relative; } .d2-inner { background-color: orange; width: 400px; font-size: 40px; line-height: 1; color: red; } </style> <div class="d1"> <div class="d1-inner">d1-inner</div> </div> <div class="d2"> <div class="d2-inner">d2-inner</div> </div>
觸發一個元素造成層疊上下文有如下方法,摘自 MDN:
根元素 (HTML)
z-index 值不爲 "auto"的 絕對/相對定位
一個 z-index 值不爲 "auto"的 flex 項目 (flex item),即:父元素 display: flex|inline-flex。(需知足兩個條件才能觸發:1是父級須要是display:flex或者display:inline-flex水平,2是子元素的z-index不是auto,必須是數值。則這個子元素爲層疊上下文元素)
opacity 屬性值小於 1 的元素(參考 the specification for opacity)
transform 屬性值不爲 "none"的元素
mix-blend-mode 屬性值不爲 "normal"的元素
filter值不爲「none」的元素
perspective值不爲「none」的元素
isolation 屬性被設置爲 "isolate"的元素
position: fixed
在 will-change 中指定了任意 CSS 屬性,即使你沒有直接指定這些屬性的值
-webkit-overflow-scrolling 屬性被設置 "touch"的元素