層疊上下文
層疊上下文(Stacking context)是 HTML 元素的三維概念,這些元素沿著一條假想的相對於使用者的 z 軸排列,使用者被假定面對著視口或網頁。層疊上下文決定了元素如何沿 z 軸(可以將其視為螢幕上的“深度”維度)相互堆疊。層疊上下文決定了重疊內容的視覺呈現順序。
層疊上下文中的元素與該上下文之外的元素是獨立堆疊的,這確保了一個層疊上下文中的元素不會干擾另一個層疊上下文中的元素的堆疊順序。每個層疊上下文都與其兄弟元素完全獨立:只有後代元素在處理堆疊時才會被考慮。
每個層疊上下文都是自包含的。在元素的內部內容完成堆疊後,整個元素在其父層疊上下文的堆疊順序中被視為一個單一的單元。
在層疊上下文中,子元素根據所有兄弟元素的 z-index 值進行堆疊。這些巢狀元素的層疊上下文僅在其父上下文中才有意義。在父層疊上下文中,層疊上下文被原子化地視為一個單一單元。層疊上下文可以包含在其他層疊上下文中,並共同建立一個層疊上下文的層級結構。
層疊上下文的層級結構是 HTML 元素層級結構的一個子集,因為只有某些元素會建立層疊上下文。不建立自身層疊上下文的元素會被父層疊上下文同化。
建立層疊上下文的特性
在文件的任何位置,只要元素滿足以下任一情況,就會形成一個層疊上下文
-
文件的根元素(
<html>)。 -
position值為fixed或sticky的元素。 -
container-type值為size或inline-size的元素(參見容器查詢)。 -
作為彈性(flex)元素,且
z-index值不為auto的元素。 -
作為網格(grid)元素,且
z-index值不為auto的元素。 -
opacity值小於1的元素。 -
mix-blend-mode值不為normal的元素。 -
以下任一屬性的值不為
none的元素 -
isolation值為isolate的元素。 -
will-change值指定了任何在非初始值時會建立層疊上下文的屬性的元素。 -
contain值為layout或paint,或包含這兩個值之一的複合值(即contain: strict、contain: content)的元素。 -
被放入頂層(top layer)的元素及其對應的
::backdrop。例如全屏和popover 元素。 -
使用
@keyframes對建立層疊上下文的屬性(如opacity)進行動畫處理,且animation-fill-mode設定為forwards的元素。
巢狀的層疊上下文
層疊上下文可以包含在其他層疊上下文中,它們可以共同建立一個層疊上下文的層級結構。
文件的根元素是一個層疊上下文,在大多數情況下,它包含巢狀的層疊上下文,其中許多又會包含更多的層疊上下文。在每個層疊上下文中,子元素都根據使用 z-index 中解釋的相同規則進行堆疊。重要的是,其子層疊上下文的 z-index 值僅在其父層疊上下文中才有意義。在父層疊上下文中,層疊上下文被原子化地視為一個單一單元。
要弄清楚堆疊元素沿 z 軸的渲染順序,可以將每個索引值想象成一種“版本號”,其中子元素代表其父元素主版本號下的次版本號。
為了演示每個元素的堆疊順序如何參與其祖先層疊上下文的堆疊順序,我們來看一個包含六個容器元素的示例頁面。其中有三個兄弟 <article> 元素。最後一個 <article> 包含三個兄弟 <section> 元素,而第三個 article 的 <h1> 和 <code> 出現在第一個和第二個兄弟 <section> 元素之間。
<article id="container1">
<h1>Article element #1</h1>
<code>
position: relative;<br />
z-index: 5;
</code>
</article>
<article id="container2">
<h1>Article Element #2</h1>
<code>
position: relative;<br />
z-index: 2;
</code>
</article>
<article id="container3">
<section id="container4">
<h1>Section Element #4</h1>
<code>
position: relative;<br />
z-index: 6;
</code>
</section>
<h1>Article Element #3</h1>
<code>
position: absolute;<br />
z-index: 4;
</code>
<section id="container5">
<h1>Section Element #5</h1>
<code>
position: relative;<br />
z-index: 1;
</code>
</section>
<section id="container6">
<h1>Section Element #6</h1>
<code>
position: absolute;<br />
z-index: 3;
</code>
</section>
</article>
每個容器元素的 opacity 都小於 1,並且 position 設定為 relative 或 absolute。當元素的 z-index 值不為 auto 時,這些屬性-值對會建立一個層疊上下文。
section,
article {
opacity: 0.85;
position: relative;
}
#container1 {
z-index: 5;
}
#container2 {
z-index: 2;
}
#container3 {
z-index: 4;
position: absolute;
top: 40px;
left: 180px;
}
#container4 {
z-index: 6;
}
#container5 {
z-index: 1;
}
#container6 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
}
為了簡潔起見,顏色、字型、對齊和盒模型的 CSS 屬性已被隱藏。
上述示例中的層疊上下文層級結構如下
Root │ ├── ARTICLE #1 ├── ARTICLE #2 └── ARTICLE #3 │ ├── SECTION #4 ├──── ARTICLE #3 content ├── SECTION #5 └── SECTION #6
這三個 <section> 元素是 ARTICLE #3 的子元素。因此,section 元素的堆疊完全在 ARTICLE #3 內部解析。一旦 ARTICLE #3 內部的堆疊和渲染完成,整個 ARTICLE #3 元素就會被傳遞到根元素中,與其兄弟 <article> 元素進行堆疊。
透過將 z-index 比作“版本號”,我們可以看到 z-index 為 1 的元素(SECTION #5)如何堆疊在 z-index 為 2 的元素(ARTICLE #2)之上,以及 z-index 為 6 的元素(SECTION #4)如何堆疊在 z-index 為 5 的元素(ARTICLE #1)之下。SECTION #4 渲染在 ARTICLE #1 之下,是因為 ARTICLE #1 的 z-index (5) 在根元素的層疊上下文中有效,而 SECTION #4 的 z-index (6) 在 ARTICLE #3 (z-index: 4) 的層疊上下文中有效。所以 SECTION #4 在 ARTICLE #1 之下,因為 SECTION #4 屬於 ARTICLE #3,而 ARTICLE #3 的 z-index 值較低(4-6 小於 5-0)。
出於同樣的原因,ARTICLE #2 (z-index: 2) 渲染在 SECTION #5 (z-index: 1) 之下,因為 SECTION #5 屬於 ARTICLE #3 (z-index: 4),而 ARTICLE #3 的 z-index 值更高(2-0 小於 4-1)。
ARTICLE #3 的 z-index 是 4,但這個值與巢狀在其中的三個 section 的 z-index 無關,因為它們屬於不同的層疊上下文。
在我們的示例中(按最終渲染順序排序)
- 根
-
ARTICLE #2: (
z-index: 2),渲染順序為2-0 -
ARTICLE #3: (
z-index: 4),渲染順序為4-0- SECTION #5: (
z-index: 1),堆疊在 (z-index: 4) 的元素下,渲染順序為4-1 - SECTION #6: (
z-index: 3),堆疊在 (z-index: 4) 的元素下,渲染順序為4-3 - SECTION #4: (
z-index: 6),堆疊在 (z-index: 4) 的元素下,渲染順序為4-6
- SECTION #5: (
-
ARTICLE #1: (
z-index: 5),渲染順序為5-0
-
其他示例
其他示例包括最後一層設定 z-index 的 2 級層級結構、所有層級都設定 z-index 的 2 級 HTML 層級結構,以及第二層設定 z-index 的 3 級 HTML 層級結構。