iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 4
4
Modern Web

前端三十 - 成為更好的前端工程師系列 第 4

04. [CSS] z-index 與 Stacking Context 的關係是什麼?

https://ithelp.ithome.com.tw/upload/images/20190920/20111380c3CeK2eEek.jpg

不知道大家有沒有這樣的經驗:在排版時無論 z-index 怎麼調整,元素仍然被其他東西蓋住,怎麼調都調不好;今天我們將會深入理解這背後的原因,一起來聊聊 z-index 及與它相關的 堆疊環境(Stacking Context)

本系列文已經重新編校彙整編輯成冊,並正式出版囉!
《前端三十:從 HTML 到瀏覽器渲染的前端開發者必備心法》好評販售中!
喜歡我文章內容的讀者們,歡迎您 前往購買 支持!

z-index

相信這個 CSS 屬性大家應該都不陌生,是用來指定元素在 z 軸的「高度」(越大越靠近使用者);在 CSS2.1 的規格 中指明:

For a positioned box, the 'z-index' property specifies:

  1. The stack level of the box in the current stacking context.
  2. Whether the box establishes a stacking context.

這邊的 positioned box 指的是 position 屬性不為預設值(static)的元素(box 指盒模型);所以 z-index 即為指定元素在 堆疊環境 中的 堆疊層級,且它只在 positioned box 上生效。

眼尖的同學應該已經注意到了,又出現了 昨天文章 就已經提到過的 Stacking Context,那麼它究竟是什麼呢?

堆疊環境 Stacking Context

在網頁排版時,預設的元素排列會是由上到下、由左到右的依序排列;開發者如果想要調整或固定特定元素的位置,會透過設定 positionrelativeabsolutefixed,讓指定的元素可以從原本的排列位置移動,甚至離開(Out of Flow)。而這時,也就產生了一個新的 CSS 堆疊環境,從此這個元素及它的子元素,就自成一國,他們的排列也就與其他的堆疊環境無關了。

功能

那這些自成一國的堆疊環境,對開發者來說有什麼影響呢?

很簡單!堆疊環境內的元素、屬性變動,是不會觸發其他堆疊環境的回流(Reflow)的喔~

rendering

昨天討論的瀏覽器的渲染步驟,其實還有最後一步:一個 Render Tree 經過計算後會轉換成許多堆疊環境,也可以理解成 圖層;我們先前聊過的「計算定位(Layout、Reflow)」、「繪製像素(Paint)」,這些步驟會發生在每一個圖層上,而瀏覽器會在最後的步驟「合成(Composite)」時,將這些圖層做疊加計算。

你可能會想問,為什麼不先疊加計算再繪製像素?
同樣的,是因為要讓各圖層的計算不會互相影響;如果某圖層只覆蓋到部分螢幕,當它樣式變動時,也只需要重算該圖層包含的部分畫面就好,不用全螢幕都重新繪製。

另外,堆疊環境也會影響到畫面的 z 軸排列順序。

回頭看一下剛剛提到的 z-index 定義,z-index 的影響範圍就只有在它所在的堆疊環境中;因此要確認兩元素的排列順序,必須先確認元素個別所在的堆疊環境順序,若在同一個堆疊環境,才比較兩者的 z-index

可以參考底下這個 MDN 的範例

https://ithelp.ithome.com.tw/upload/images/20190920/20111380q9tK75vtia.jpg

範例中的 #div1#div2#div3 是同層元素,共用了最外層的「根堆疊環境(Root Stacking Context)」,而 #div4#div5#div6 則是 #div3 的子元素。

由於 #div3 有設定 position: absolutez-index: 3,它會產生一個新的堆疊環境,即使 #div2z-index 大於 #div5z-index,卻因為它們存在於不同的堆疊環境中,它們之間不會直接比較,而是從共用堆疊環境的 #div2#div3 中 比較 z-index,來決定 z 軸上的排列順序。

建立堆疊環境

要建立一個新的堆疊環境非常容易,比較常用到的有以下幾種方式:

  • 根元素(<html></html>
  • position 設定成 fixedsticky
  • position 設定成 relativeabsolute & 有設定 z-index
  • 有設定 transform 屬性
  • opacity 的值設定小於 1

另外,開發者可以透過瀏覽器 DevTools 的 Layers 頁籤,觀察目前的頁面有哪些圖層:

https://ithelp.ithome.com.tw/upload/images/20190920/20111380zHnkM9Q43g.jpg

如同前述,瀏覽器會將所有圖層做疊加運算;當圖層過多時也會稍微影響效能,在撰寫 CSS 時要稍微留心喔!

延伸閱讀

雖然聊了兩天的 CSS 中相對深入的主題,但對於瀏覽器渲染畫面這塊仍然只帶到皮毛;關於 Render Tree 轉換成堆疊環境的過程,讀者如果想要進一步探究的話,可以參考 這篇,但內容會偏離 CSS 太遠,這邊就不繼續深入了。

結語

在研究這個主題時,突然發現很多以前覺得 CSS 玄妙的地方,好像都可以跟 Stacking Context 扯上關係;例如設定絕對定位時為什麼是參考外層的 positioned box 等等,真的有種被醍醐灌頂、打通任督二脈的感覺;果然在理解基本原理之後,許多難懂的知識點都可以迎刃而解!

聊了兩天的 CSS 明天就是 CSS 的最後一部啦!以上就是今天的 Stacking Context,如果本文有任何錯誤或不清楚的地方,都歡迎讀者您在底下留言回應!這場每天讓自己更好的旅程將會繼續下去,大家明天見囉~

參考資料

筆者

Gary

半路出家網站工程師;半生熟的前端加上一點點的後端。
喜歡音樂,喜歡學習、分享,也喜歡當個遊戲宅。

相信一切安排都是最好的路。


上一篇
03. [CSS] Reflow 及 Repaint 是什麼?
下一篇
05. [CSS] 元素選取器是如何運作的?
系列文
前端三十 - 成為更好的前端工程師31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言