介紹 Box, Reflow, Render pipeline 等
首先瀏覽器上每個元素都是 Box,而每個 Box 分成了 4 個部分,包含了:
Box 有 2 種屬性 Size 以及 Generation,Size 可以分為:
當 Box Size 是 Intrinsic 時,Box 會使用內容當作該 Box 的空間,不考慮外部環境影響;當 Box Size 是 Extrinsic 時,Box 會透過 CSS 設定空間或是被父元素控制空間。
Intrinsic Size 的範例:
如 <span>
就是一個很好的 Intrinsic Size 的元素,他是個 inline
的元素,所以設定寬高都不會影響到他,只會根據文字的長度決定寬,文字的 line-height
決定此元素的高。
<span>Hello</span>
如果要設定一個元素是最小的 Intrinsic Size,可以使用 width: min-content
,此時會盡可能地進行換行,最後的寬度會由最長的詞為寬度。
<div class="min-intrinsic-size">This is a long long long long sentence</div>
<style>
.min-intrinsic-size {
width: min-content;
}
</style>
另外像是圖片,如果有一張長寬爲 800x600 的圖片,在未進行設定的情況下,它就會以 800x600 的方式自然呈現。
<img src="photo800x600.jpg">
Extrinsic 的範例:
例如 CSS 使用了 aspect-ratio
,定義了寬高比,內容大小被父原素限定住了,就是 Extrinsic Size
.box {
width: 100%;
aspect-ratio: 16 / 9;
}
或是由父元素去設定寬高,決定內容的空間
<div class="box">
<p>Content Content Content</p>
</div>
<style>
width: 200px; height: 100px; overflow: auto;
</style>
Box Generation 可以分為以下 3 種:
首先 Block 會 100% 的填滿父元素的寬,高是 Intrinsic 由內容決定高度,然後會由上至下進行 Render,並且會加入 BFC 排版,常見的元素有 div
, p
, address
, articale
等。
Anonymous 則是未被元素包起來的內容例如:
<div>Hello</div>
Hello <--- anonymouse box
Anonymous 是由瀏覽器自動生成的,沒辦法透果 CSS 選擇器選到。
下一個是 Inline 它的渲染方式是像是字串,並且會加入 IFC 排版,它的特性是會不生效所設定的寬高和垂直的 margin (水平的仍然是生效的),它的高度會受到 line-height
所影響,但 padding 不會真的影響到它的高,常見的元素有 button
, a
, i
, label
等。
Formatting Context 是一個區塊、範圍,當 Element 進入 Formatting Context,Element 就會依照它的規則進行呈現。
例如以 BFC(Block Formatting Context) 來說,在內的元素會填滿父元素,並由上到下進行排列。
IFC(Inline Formatting Context) 中的元素會依照由右至左進行排列,寬度則是 Intrinsic 的。
Formatting Context 有著:
在預設的情況下,瀏覽器的定位會依照 Normal Flow 進行排列(RTL, LTR),在建立元素的時候預設是 static
此時是無法透過設定 left
, right
, bottom
, top
去進行設定。
relative
元素仍然是在 Normal Flow 中,會建立新的 Stacking Content,可以相對於 Containing Block 去進行相對的定位(使用 left
, right
等定位,預設是左上角)。
absolute
會完全脫離 Normal Flow 中,會建立新的 Stacking Content,其他的元素會忽略此元素進行排列,會依照 Containing Block 進行定位。
首先瀏覽器在渲染時,會透過 HTML 產生 DOM Tree,以及 Style 的 CSSOM(CSS Object Model),之後會將 2 者結合爲 Render Tree 。
Render Tree 會由 Root 開始進行渲染,遇到不顯示的會忽略 (display: none
, meta
, link
),之後會和 CSSOM 的規則應用在各 node 上。
其中當 DOM 改變(新增、移除、改變位置)發生時,會產生 Reflow :
Reflow 的示意影片:
在 Style 以及 Layout 的部分會使用 CPU 去執行,會阻塞到 main thread,所以當執行過多次的 Reflow 就有可能造成畫面卡的現象。
例如:
@keyframes moving-down-slow {
from {
margin-top: 0;
}
to {
margin-top: 500px;
}
}
@keyframes moving-down-fast {
from {
transform: translateY(0px);
}
to {
transform: translateY(500px);
}
}
這 2 個 style 動畫所做的事是相同的,但在第一個使用了 margin
會導致 Reflow 的產生,若是使用下方的 transform
則不會影響到 Layout。
哪些 CSS 會觸發 Layout 可以參考 https://css-triggers.com/ 會顯示哪些屬性 Trigger 了不同的 Step 。
Layer 的存在是為了優化網頁的渲染,如果每個 Render Tree 都需要透過 CPU 進行一個個的渲染效率非常差,若可以一起進行則效率會變得更好。
Layer 有分成 2 種類型,一是一般的 Render Layer,另一個是 Composition Layer。
Render Layer 會在以下以時候建立:
position: relative
或是 absolute
並使用了 transform
transparent
<div class="filter">Filter Render Layer</div>
<style>
.filter {
will-change: filter;
filter: blur(5px);
}
</style>
當該層 Layer 做出不影響 Layout 的更新時,不會影響到整體頁面的更新,減少不必要的重繪。
Composition Layer 則適用於 3D 或是動畫的狀況,它會使用到 GPU 加速繪製,在 Render Layer 滿足以下狀況會變成 Composition Layer:
perspective
Composition Layer 會建立 thread 並使用 GPU 加速,所以可以一邊進行動畫一邊執行複雜的任務也不會造成卡頓的問題。
https://webperf.tips/tip/layers-and-compositing/
https://developer.mozilla.org/en-US/docs/Glossary/Intrinsic_Size
https://dev.to/gopal1996/understanding-reflow-and-repaint-in-the-browser-1jbg?__readwiseLocation=