在網頁排版與元素定位的過程中,position 和 z-index 是非常常見,但也容易令人混淆的 CSS 屬性。本文透過一段簡單的 HTML + CSS 範例,探討「子元素的位置」如何受到這些屬性的影響,並進一步解析 stacking context(堆疊上下文)的運作邏輯。
範例程式碼如下
<div style = "position: relative; width: 300px; height: 300px; background: lightyellow; top: 150px; left: 250px; border: 2px solid; z-index: -2;">
<div style = "position: absolute; z-index: 77; top: 5px; left: 90px; width: 60px; height: 70px; background: lightgreen;">lll
<div style = "position: absolute; top: 8px; left: 20px; z-index: 89; width: 300px; height: 30px; background: violet;">AAAAAAAAAA</div>
</div>
<div style = "position: absolute; z-index: 88; left: 70px; top: 22px; width: 60px; height: 40px; background: lightblue;">BBBBB</div>
<div style = "position: absolute; z-index: 99; left: 80px; top: 33px; width: 60px; height: 40px; background: lightgray;">CCCCC</div>
</div>
請注意:閱讀本篇文章前,最好對 CSS 的堆疊機制、z-index 的定義與作用、Stacking Context 的定義與重要性、建立 Stacking Context 的條件、及 HTML DOM,略具基礎。
範例程式碼分析
本文將分析的範例程式碼包含一個外層容器 (黃色 div),其 position 設為 relative。內部包含四個 position: absolute 的區塊:三個兄弟元素(綠色、藍色、灰色),以及一個巢狀於綠色區塊內部的紫色子元素。
黃色元素是 <body> 的子元素,綠色、藍色、灰色是黃色元素的子元素,而紫色則是綠色元素的子元素。這種嵌套結構是理解 Stacking Context 影響的關鍵。
未設定 z-index 時的預設顯示順序
當所有 div 元素都未設定 z-index 時,瀏覽器會根據其在 HTML結構中的出現順序 (DOM 樹順序)以及定位情況來決定堆疊層級。對於定位元素,後出現的元素會覆蓋先出現的元素。根據範例的 DOM 結構,預設的顯示順序 (由底到頂)為:黃 → 綠 → 紫 → 藍 → 灰。這是因為在沒有明確 z-index 的情況下,元素會按照其在文檔流中的順序進行堆疊,後者覆蓋前者。
初始 z-index 設定與顯示順序
範例中的初始 z-index 設定如下:
- 黃色背景:z-index: -2
- 綠色背景:z-index: 77
- 藍色背景:z-index: 88
- 灰色背景:z-index: 99
- 紫色背景(子元素,巢狀於綠色內部): z-index: 89
在這些設定下,觀察到的顯示順序(由底至頂)為:黃 (-2) → 綠 (77) → 紫 (89) → 藍 (88) → 灰 (99)
這個初始順序的形成,揭示了 Stacking Context 的初步影響。黃色元素由於 position: relative 且 z-index 不為 auto,建立了一個 Stacking Context。綠色元素也因同樣原因建立了自己的 Stacking Context。在黃色元素的 Stacking Context 內,其子元素 (綠、藍、灰)將根據其 z-index 值進行堆疊。由於綠色元素本身建立了一個 Stacking Context,紫色元素 (作為綠色的子元素)的 z-index 僅在綠色這個 Stacking Context 內部有意義。因此,綠色元素作為一個整體,與藍色和灰色元素在黃色元素的上下文中進行比較。在綠色內部,紫色元素根據其 z-index 值相對於綠色元素的背景進行堆疊。
z-index 調整實驗與觀察
以下實驗旨在進一步探討 z-index 和 Stacking Context 之間的複雜關係。
調整一:紫色元素 z-index: -1
- 設定:黃 (-2), 綠 (77), 紫 (-1), 藍 (88), 灰 (99)。
- 觀察到的順序:黃 (-2) → 綠 (77) → 紫 (-1) → 藍 (88) → 灰 (99) 。
這個觀察結果與初始設定下的順序相同,說明了紫色元素的 z-index 無論設為 89 或 -1,都無法跨越其父元素 (綠色區塊)所建立的 Stacking Context 限制。也就是說:一旦一個元素建立了 Stacking Context,其所有子元素的堆疊行為都將被限制在這個上下文內部。即使子元素的 z-index 值在理論上可能高於其父級上下文中的其他元素,它也無法「穿透」其父級 Stacking Context 的邊界。紫色元素雖然 z-index 為 -1,但它仍位於綠色元素所建立的 Stacking Context 內部,因此它會堆疊在綠色元素的背景之上(請參考上面觀察到的順序所示),但整個綠色元素 (包含紫色子元素)仍然作為一個整體,根據綠色元素自身的 z-index 值,在黃色元素的 Stacking Context 內進行堆疊。
調整二:綠色元素 z-index: auto,紫色元素 z-index: -1
- 設定:黃 (-2), 綠 (auto), 紫 (-1), 藍 (88), 灰 (99)。
- 觀察到的順序:黃 (-2) → 紫 (-1) → 綠 (auto) → 藍 (88)→ 灰 (99)。
這個調整產生了顯著的變化。當綠色元素的 z-index 設為 auto 時,它不再建立新的 Stacking Context。這導致綠色元素及其子元素 (紫色)都參與到黃色元素的 Stacking Context 中。在黃色元素的上下文中,負 z-index 的定位元素 (紫色 -1)會被放置在 z-index: auto 或 z-index: 0 的定位元素 (綠色 auto)之下。因此,紫色元素能夠被排在綠色元素的下面。這個結果明確地揭示了 z-index: auto 的作用:它使得元素不建立新的 Stacking Context,從而允許其子元素與更上層的祖先元素共享同一堆疊上下文,並在該上下文中進行堆疊比較。
調整三:綠色元素 z-index: auto,紫色元素 z-index: 89
- 設定:黃 (-2), 綠 (auto), 紫 (89), 藍 (88), 灰 (99)。
- 觀察到的順序:黃 (-2) → 綠 (auto) → 藍 (88) → 紫 (89) → 灰 (99)。
此調整進一步驗證了 z-index: auto 的行為。由於綠色元素的 z-index 設為 auto,它不建立新的 Stacking Context。這使得綠色、紫色、藍色、灰色元素都參與到黃色元素的 Stacking Context 中。在黃色元素的 Stacking Context 內部,這些元素會根據其 z-index 值和類型進行堆疊。根據 CSS 堆疊規則,z-index: auto 的定位元素 (綠色)會排在所有負 z-index 元素之上,但在所有正 z-index 元素之下。而正 z-index 的定位元素 (藍色 88、紫色 89、灰色 99)則按照其 z-index 值從低到高排序。因此紫色元素 (89)能夠與其父元素 (綠色)的兄弟元素 (藍 88、灰 99)進行 z-index 比較,並根據其值決定最終的顯示順序。這再次強調了當父元素不建立 Stacking Context 時,子元素的堆疊行為會被提升到父元素的父級上下文進行評估。
結論:掌握 Stacking Context 與 z-index 的運作邏輯,是建立穩固前端版面結構的重要基礎。希望這篇實驗與解析,能幫助你在排版時做出更可預期的層級控制!
沒有留言:
張貼留言
請注意 : 您的留言發佈成功 , 需經審核後 , 才能決定是否回覆 . 謝謝 !!