前言:關(guān)于層疊上下文川尖,筆者還沒有去閱讀更詳細(xì)的 W3C 規(guī)范來了解更本質(zhì)的原理(表打我赎败,等我校招拿到 offer 了我就讀好伐 T_T)潜慎。一直聽說 CSS3 里的層疊上下文有新情況,但沒找到很好的參考資料子姜,故自己實(shí)戰(zhàn)一把洗做。鑒于筆者水平有限,如有任何遺漏或者錯(cuò)誤址芯,則懇請讀者斧正灾茁。
1 CSS2.1 中規(guī)定的層疊上下文
Background and borders — of the element forming the stacking context. The lowest level in the stack.
Negative Z-Index — the stacking contexts of descendants elements with negative z-index.
Block Level Boxes — in-flow non-inline-level non-positioned descendants.
Floated Boxes — non-positioned floats
Inline Boxes — in-flow inline-level non-positioned descendants.
Z-index: 0 — positioned elements. These form new stacking contexts.
Positive Z-index — positioned elements. The highest level in the stack.
圖文來源:What You May Not Know About the Z-Index Property
現(xiàn)在該筆者上場翻譯了窜觉!在解釋上面術(shù)語之前,需要闡明兩個(gè)術(shù)語:“定位”指的是position
為relative
北专、absolute
禀挫、fixed
的元素,“非定位”則相反拓颓。
- 背景和邊框:建立層疊上下文元素的背景和邊框语婴。層疊中的最低級
-
負(fù) Z-index:
z-index
為負(fù)的后代元素建立的層疊上下文 - 塊級盒:文檔流內(nèi)非行內(nèi)級非定位后代元素
-
浮動(dòng)盒:非定位浮動(dòng)元素(筆者注:即排除了
position: relative
的浮動(dòng)盒) - 行內(nèi)盒:文檔流內(nèi)行內(nèi)級非定位后代元素
- Z-index: 0:定位元素。這些元素建立了新層疊上下文(筆者注:不一定驶睦,詳見后文)
-
正 Z-index:(
z-index
為正的)定位元素砰左。層疊的最高等級
引文如上所表。但筆者提醒各位讀者一點(diǎn)场航,“Z-index: 0
”級的定位元素不一定就會建立新的層疊上下文缠导。因?yàn)椋?/p>
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.
當(dāng)定位元素z-index: auto
,生成盒在當(dāng)前層疊上下文中的層級為0
溉痢。但該盒不建立新的層疊上下文僻造,除非是根元素。
規(guī)范是這樣孩饼,但 IE6-7 有個(gè) BUG髓削,定位元素即便z-index: auto
照樣創(chuàng)建層疊上下文。
以上是基于 CSS2.1 的層疊上下文介紹镀娶。下面要闡述的是在 CSS3 新環(huán)境下立膛,層疊上下文的新變化。
2 CSS3 帶來的變化
總的來說變化可以歸為兩點(diǎn)梯码,我們之后一一探討:
- CSS3 中許多屬性會創(chuàng)建局部層疊上下文
- tranform屬性改變絕對定位子元素的包含塊
2.1 產(chǎn)生新層疊上下文的情況
以下情況會產(chǎn)生新的層疊上下文:
- 根元素(HTML)
- 絕對或相對定位且
z-index
值不為auto
- 一個(gè)伸縮項(xiàng)目
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
以上列表譯自:
Understanding CSS z-index—The stacking context鲁猩,提醒廣大讀者,別看中文版罢坝,因?yàn)橹形陌娌⒎菍?shí)時(shí)跟進(jìn)更新的廓握,且翻譯不太準(zhǔn)確
2.2 提升層疊上下文中的層級
以上元素建立新層疊上下文的同時(shí),也會提升元素自身所在層疊上下文中的層級嘁酿。
我們以opacity
為例隙券。來看下 CSS3 規(guī)范中的話:
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 ‘a(chǎn)uto’ 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 應(yīng)用游桩,但auto
要視為0
牲迫,因?yàn)樾碌膶盈B上下文總是創(chuàng)建了的耐朴。
如下案例:
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 是文檔流內(nèi)塊級盒(層級為“塊級盒”級)筛峭,因此 box1 會層疊在 box2 之上。下面添加如下 CSS 規(guī)則:
#box2 {
opacity: .5;
}
這時(shí)候陪每, box2 則會層疊在 box1 之上了影晓。因?yàn)?box2 的opacity
為0.5
(小于 1),故視其為“Z-index: 0
”級檩禾,也就和 box1 同級了挂签。同級情況下,按照二者在源代碼中的順序盼产,居后的 box2 又重新占領(lǐng)高地了饵婆。
讀者可以取下面規(guī)則之任意一條實(shí)驗(yàn),都能達(dá)到同樣效果:
#box2 {
transform: scale(1);
mix-blend-mode: difference;
isolation: isolate;
-webkit-filter: blur(5px);
}
2.3 transform 改變絕對定位子元素包含塊
transform
除了建立新的局部層疊上下文外辆飘,還會干一件事:改變絕對定位子元素的包含塊啦辐。須注意的是谓传,固定定位也是絕對定位的一種蜈项。
什么是包含塊?有時(shí)候一些盒子根據(jù)矩形盒計(jì)算自身定位和大小续挟,此矩形盒即包含塊紧卒。更多詳情請閱讀視覺格式化模型詳述。
固定定位元素
固定定位元素的包含塊由視口創(chuàng)建(如果讀者了解視覺格式化模型詳述的信息诗祸,也就知道這一點(diǎn):在計(jì)算其“靜態(tài)位置”的時(shí)候跑芳,則以初始化包含塊作為其計(jì)算包含塊)。現(xiàn)在我們看以下源代碼:
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>
這個(gè)時(shí)候直颅,以視口為包含塊進(jìn)行定位和大小計(jì)算博个, fixed
將會鋪滿整個(gè)屏幕。
但現(xiàn)在功偿,我們加上如下規(guī)則:
#transform {
transform: scale(1);
}
此時(shí)盆佣,fixed
的包含塊不再是視口,而是transform
的內(nèi)邊距盒的邊緣盒了械荷。故此時(shí)fixed
的寬高均為140px
共耍。
絕對定位元素
我們舉一個(gè)例子:
#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>
此時(shí)absolute
的包含塊為relative
的內(nèi)邊距盒的邊緣盒。由此absolute
的寬高均為100px
吨瞎。然后我們添加如下規(guī)則:
#transform {
transform: scale(1);
}
由于transform
創(chuàng)建了局部層疊上下文痹兜,absolute
的包含塊不再是 relative
而是transform
了,根據(jù)這一新的包含塊颤诀,得新寬和高為50px
字旭。