CSS3 中的層疊上下文初探

作者:HaoyCn
文章源自:https://segmentfault.com/a/1190000003825614

前言:關(guān)于層疊上下文,筆者還沒(méi)有去閱讀更詳細(xì)的 W3C 規(guī)范來(lái)了解更本質(zhì)的原理(表打我,等我校招拿到 offer 了我就讀好伐 T_T)。一直聽(tīng)說(shuō) CSS3 里的層疊上下文有新情況,但沒(méi)找到很好的參考資料,故自己實(shí)戰(zhàn)一把。鑒于筆者水平有限,如有任何遺漏或者錯(cuò)誤,則懇請(qǐng)讀者斧正。

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.

圖文來(lái)源:What You May Not Know About the Z-Index Property

現(xiàn)在該筆者上場(chǎng)翻譯了!在解釋上面術(shù)語(yǔ)之前,需要闡明兩個(gè)術(shù)語(yǔ):“定位”指的是positionrelativeabsolute、fixed的元素,“非定位”則相反。

  • 背景和邊框:建立層疊上下文元素的背景和邊框。層疊中的最低級(jí)
  • 負(fù) Z-indexz-index為負(fù)的后代元素建立的層疊上下文
  • 塊級(jí)盒:文檔流內(nèi)非行內(nèi)級(jí)非定位后代元素
  • 浮動(dòng)盒:非定位浮動(dòng)元素(筆者注:即排除了 position: relative的浮動(dòng)盒)
  • 行內(nèi)盒:文檔流內(nèi)行內(nèi)級(jí)非定位后代元素
  • Z-index: 0:定位元素。這些元素建立了新層疊上下文(筆者注:不一定,詳見(jiàn)后文)
  • 正 Z-index:(z-index為正的)定位元素。層疊的最高等級(jí)

引文如上所表。但筆者提醒各位讀者一點(diǎn),“Z-index: 0”級(jí)的定位元素不一定就會(huì)建立新的層疊上下文。因?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)前層疊上下文中的層級(jí)為0。但該盒不建立新的層疊上下文,除非是根元素。

規(guī)范是這樣,但 IE6-7 有個(gè) BUG,定位元素即便z-index: auto照樣創(chuàng)建層疊上下文。

以上是基于 CSS2.1 的層疊上下文介紹。下面要闡述的是在 CSS3 新環(huán)境下,層疊上下文的新變化。

2 CSS3 帶來(lái)的變化

總的來(lái)說(shuō)變化可以歸為兩點(diǎn),我們之后一一探討:

  1. CSS3 中許多屬性會(huì)創(chuàng)建局部層疊上下文
  2. tranform屬性改變絕對(duì)定位子元素的包含塊

2.1 產(chǎn)生新層疊上下文的情況

以下情況會(huì)產(chǎn)生新的層疊上下文:

  • 根元素(HTML)
  • 絕對(duì)或相對(duì)定位且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中指定了上述任意屬性,即便你沒(méi)有直接定義這些屬性元素的-webkit-overflow-scrolling屬性值為touch

以上列表譯自:

Understanding CSS z-index—The stacking context,提醒廣大讀者,別看中文版,因?yàn)橹形陌娌⒎菍?shí)時(shí)跟進(jìn)更新的,且翻譯不太準(zhǔn)確

2.2 提升層疊上下文中的層級(jí)

以上元素建立新層疊上下文的同時(shí),也會(huì)提升元素自身所在層疊上下文中的層級(jí)。

我們以opacity為例。來(lái)看下 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: 0opacity: 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 是絕對(duì)定位(層級(jí)為“Z-index: 0”級(jí)),而 box2 是文檔流內(nèi)塊級(jí)盒(層級(jí)為“塊級(jí)盒”級(jí)),因此 box1 會(huì)層疊在 box2 之上。下面添加如下 CSS 規(guī)則:

#box2 {
    opacity: .5;
}

這時(shí)候, box2 則會(huì)層疊在 box1 之上了。因?yàn)?box2 的opacity0.5(小于 1),故視其為“Z-index: 0”級(jí),也就和 box1 同級(jí)了。同級(jí)情況下,按照二者在源代碼中的順序,居后的 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 改變絕對(duì)定位子元素包含塊

transform除了建立新的局部層疊上下文外,還會(huì)干一件事:改變絕對(duì)定位子元素的包含塊。須注意的是,固定定位也是絕對(duì)定位的一種。

什么是包含塊?有時(shí)候一些盒子根據(jù)矩形盒計(jì)算自身定位和大小,此矩形盒即包含塊。更多詳情請(qǐng)閱讀視覺(jué)格式化模型詳述。

固定定位元素

固定定位元素的包含塊由視口創(chuàng)建(如果讀者了解視覺(jué)格式化模型詳述的信息,也就知道這一點(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將會(huì)鋪滿整個(gè)屏幕。

但現(xiàn)在,我們加上如下規(guī)則:

#transform {
    transform: scale(1);
}

此時(shí),fixed的包含塊不再是視口,而是transform的內(nèi)邊距盒的邊緣盒了。故此時(shí)fixed的寬高均為140px

絕對(duì)定位元素

我們舉一個(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。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 問(wèn)答題47 /72 常見(jiàn)瀏覽器兼容性問(wèn)題與解決方案? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,108評(píng)論 1 92
  • 引自:張?chǎng)涡竦牟┛捅疚牡刂罚篽ttp://www.zhangxinxu.com/wordpress/?p=5115...
    destiny0904閱讀 1,910評(píng)論 1 0
  • 1.z-index基礎(chǔ) z-index屬性指定了元素及其子元素的[z順序],而[z順序]可以決定當(dāng)元素發(fā)生覆蓋的時(shí)...
    徐國(guó)軍_plus閱讀 6,589評(píng)論 1 6
  • z-index 與 css 定位屬性 z-index 只對(duì)定位元素有作用。 如果定位元素z-index沒(méi)有發(fā)生嵌套...
    soojade閱讀 1,046評(píng)論 0 2
  • 因?yàn)橐粓?chǎng)夢(mèng)境,那些漸被遺忘又悄悄顯露的癡心雜念,繼續(xù)叨擾著生活。半夜騰起也只為一場(chǎng)記起。人的痛苦或幸福在于,無(wú)論怎...
    青春被忘路閱讀 223評(píng)論 0 0

友情鏈接更多精彩內(nèi)容