前言:關於層疊上下文,筆者尚未去閱讀更詳細的 W3C 規範來了解更本質的原理(表打我,等我校招拿到 offer 了我就讀好伐 T_T)。一直據說 CSS3 裏的層疊上下文有新狀況,但沒找到很好的參考資料,故本身實戰一把。鑑於筆者水平有限,若有任何遺漏或者錯誤,則懇請讀者斧正。web
Background and borders — of the element forming the stacking context. The lowest level in the stack.app
Negative Z-Index — the stacking contexts of descendants elements with negative z-index.less
Block Level Boxes — in-flow non-inline-level non-positioned descendants.flex
Floated Boxes — non-positioned floatsspa
Inline Boxes — in-flow inline-level non-positioned descendants.翻譯
Z-index: 0 — positioned elements. These form new stacking contexts.code
Positive Z-index — positioned elements. The highest level in the stack.orm
如今該筆者上場翻譯了!在解釋上面術語以前,須要闡明兩個術語:「定位」指的是 position
爲 relative
、absolute
、fixed
的元素,「非定位」則相反。ci
背景和邊框:創建層疊上下文元素的背景和邊框。層疊中的最低級
負 Z-index:z-index
爲負的後代元素創建的層疊上下文
塊級盒:文檔流內非行內級非定位後代元素
浮動盒:非定位浮動元素(筆者注:即排除了 position: relative
的浮動盒)
行內盒:文檔流內行內級非定位後代元素
Z-index: 0:定位元素。這些元素創建了新層疊上下文(筆者注:不必定,詳見後文)
正 Z-index:(z-index
爲正的)定位元素。層疊的最高等級
引文如上所表。但筆者提醒各位讀者一點,「Z-index: 0」級的定位元素不必定就會創建新的層疊上下文。由於:
CSS2.1:(z-index: auto)The stack level of the generated box in the current stacking context is 0. The box does not establish a new stacking context unless it is the root element.
當定位元素 z-index: auto
,生成盒在當前層疊上下文中的層級爲 0。但該盒不創建新的層疊上下文,除非是根元素。
規範是這樣,但 IE6-7 有個 BUG,定位元素即使 z-index: auto
照樣建立層疊上下文。
以上是基於 CSS2.1 的層疊上下文介紹。下面要闡述的是在 CSS3 新環境下,層疊上下文的新變化。
總的來講變化能夠歸爲兩點,咱們以後一一探討:
CSS3 中許多屬性會建立局部層疊上下文
tranform
屬性改變絕對定位子元素的包含塊
如下狀況會產生新的層疊上下文:
根元素(HTML)
絕對或相對定位且 z-index
值不爲 auto
一個伸縮項目 Flex Item
,且 z-index
值不爲 auto
,即父元素 display: flex|inline-flex
元素的 opacity
屬性值小於 1
元素的 transform
屬性值不爲 none
元素的 mix-blend-mode
屬性值不爲 normal
元素的 filter
屬性值不爲 normal
元素的 isolation
屬性值爲 isolate
position: fixed
will-change
中指定了上述任意屬性,即使你沒有直接定義這些屬性
元素的 -webkit-overflow-scrolling
屬性值爲 touch
以上列表譯自:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context,提醒廣大讀者,別看中文版,由於中文版並不是實時跟進更新的,且翻譯不太準確
以上元素創建新層疊上下文的同時,也會提高元素自身所在層疊上下文中的層級。
咱們以 opacity
爲例。來看下 CSS3 規範中的話:
If an element with opacity less than 1 is not positioned, implementations must paint the layer it creates, within its parent stacking context, at the same stacking order that would be used if it were a positioned element with ‘z-index: 0’ and ‘opacity: 1’. If an element with opacity less than 1 is positioned, the ‘z-index’ property applies as described in [CSS21], except that ‘auto’ is treated as ‘0’ since a new stacking context is always created.
若是元素 opacity
小於 1 且未定位,則必須在其父層疊上下文中,按其在定位了的、z-index: 0
且 opacity: 1
的狀況中的層疊順序繪製。若是 opacity
小於 1 且已定位,z-index
屬性按 CSS2.1 應用,但 auto
要視爲 0
,由於新的層疊上下文老是建立了的。
以下案例:
div { width: 100px; height: 100px; } #box1 { position: absolute; background: red; top: 40px; left: 40px; } #box2 { background: blue; } <body> <div id="box1"></div> <div id="box2"></div> <body>
以上 CSS 和 HTML 片斷中,因爲 box1 是絕對定位(層級爲「Z-index: 0」級),而 box2 是文檔流內塊級盒(層級爲「塊級盒」級),所以 box1 會層疊在 box2 之上。下面添加以下 CSS 規則:
#box2 { opacity: .5; }
這時候, box2 則會層疊在 box1 之上了。由於 box2 的 opacity
爲 0.5(小於 1),故視其爲「Z-index: 0」級,也就和 box1 同級了。同級狀況下,按照兩者在源代碼中的順序,居後的 box2 又從新佔領高地了。
讀者能夠取下面規則之任意一條實驗,都能達到一樣效果:
#box2 { transform: scale(1); mix-blend-mode: difference; isolation: isolate; -webkit-filter: blur(5px); }
transform
除了創建新的局部層疊上下文外,還會幹一件事:改變絕對定位子元素的包含塊。須注意的是,固定定位也是絕對定位的一種。
什麼是包含塊?有時候一些盒子根據矩形盒計算自身定位和大小,此矩形盒即包含塊。更多詳情請閱讀視覺格式化模型詳述。
固定定位元素
固定定位元素的包含塊由視口建立(若是讀者瞭解視覺格式化模型詳述的信息,也就知道這一點:在計算其「靜態位置」的時候,則以初始化包含塊做爲其計算包含塊)。如今咱們看如下源代碼:
div { width: 100px; height: 100px; } #fixed { position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: blue; } #transform { background: red; padding: 20px; } <body> <div id="transform"> <div id="fixed"></div> </div> </body>
這個時候,以視口爲包含塊進行定位和大小計算, fixed 將會鋪滿整個屏幕。
但如今,咱們加上以下規則:
#transform { transform: scale(1); }
此時,fixed 的包含塊再也不是視口,而是 transform 的內邊距盒的邊緣盒了。故此時 fixed 的寬高均爲 140px。
絕對定位元素
咱們舉一個例子:
#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; } <div id="relative"> <div id="transform"> <div id="absolute"></div> </div> </div>
此時 absolute 的包含塊爲 relative 的內邊距盒的邊緣盒。由此 absolute 的寬高均爲 100px。而後咱們添加以下規則:
#transform { transform: scale(1); }
因爲 transform 建立了局部層疊上下文,absolute 的包含塊再也不是 relative 而是 transform 了,根據這一新的包含塊,得新寬和高爲 50px。