快轉到主要內容
  1. Core/

瀏覽器渲染流程|Reflow vs Repaint 與效能優化

Idle Engineer
作者
Idle Engineer
AI Runs. I Nap. | 404 Career Not Found
目錄

TL;DR | 面試情境模擬
#

👴 面試官:瀏覽器渲染的流程是什麼?Reflow 和 Repaint 有什麼差別?

🧑‍💻 :瀏覽器拿到 HTML 後依序做:解析 HTML 建立 DOM Tree、解析 CSS 建立 CSSOM Tree、合併成 Render Tree、計算每個元素的位置和大小(Layout)、決定每個像素的顏色(Paint)、把各層合併到螢幕(Composite)。Reflow 是改變了影響排版的屬性(如 width、height、font-size),要重新從 Layout 開始算,成本最高。Repaint 只改了顏色或背景,不影響排版,跳過 Layout 直接 Paint。Composite 只改了 transform 或 opacity,只在合成層做,不影響 Layout 和 Paint,成本最低。


比喻:蓋房子
#

DOM  = 房子的磚牆結構
CSSOM = 設計圖(顏色、材質、大小)
Render Tree = 知道哪些磚塊要顯示,合計後的施工計劃
Layout = 測量每塊磚的實際位置和尺寸
Paint = 粉刷每塊磚
Composite = 把各個房間拼在一起變成完整的家

完整渲染流程
#

HTML bytes
DOM Tree  +  CSSOM Tree
    │              │
    └──── 合併 ────┘
      Render Tree(只含可見元素)
        Layout(計算位置和尺寸)
         Paint(像素著色)
       Composite(圖層合成)
         螢幕

各階段說明
#

階段 做什麼 觸發範例
DOM Construction 解析 HTML tag,建立節點樹 初次載入
CSSOM Construction 解析 CSS,建立樣式規則樹 初次載入
Render Tree 合併 DOM + CSSOM,排除 display:none 的節點 初次載入
Layout(Reflow) 計算每個元素的位置、大小 width/height/margin 改變
Paint(Repaint) 填充像素顏色、背景、邊框 color/background 改變
Composite 把各圖層合成最終畫面 transform/opacity 改變

Reflow vs Repaint vs Composite
#

Reflow(最貴):
  改變任何影響排版的屬性
  width, height, padding, margin, font-size, top, left...
  → 從 Layout 重新算 → Paint → Composite

Repaint(中等):
  改變不影響排版的視覺屬性
  color, background, visibility, border-color...
  → 跳過 Layout → 從 Paint 開始

Composite(最便宜):
  只改合成層屬性
  transform, opacity
  → 跳過 Layout 和 Paint → 只做 Composite
  → 可以在 GPU 上執行,不阻塞主執行緒

效能優化:能用 transform 就不用 top/left
#

/* 慢:觸發 Reflow */
.box { left: 100px; top: 50px; }

/* 快:只觸發 Composite */
.box { transform: translate(100px, 50px); }

JavaScript 和渲染的關係
#

JS 執行 → Style → Layout → Paint → Composite

JavaScript 跑在主執行緒,和渲染競爭。如果 JS 執行時間超過 16ms(60fps 的一格),就會掉幀(Jank)。

優化方法

  • 長任務拆成小塊,用 requestAnimationFrame 在渲染前執行
  • 避免 Layout Thrashing(反覆讀寫 DOM 幾何屬性)
  • 耗時計算放到 Web Worker

💡 面試官可能會追問
#

Q1:script 標籤放在 head 還是 body 底部,有什麼差別?
#

<script> 預設會阻塞 HTML 解析(因為 JS 可能修改 DOM)。放在 <head> 且沒有 async/defer 屬性,會暫停 DOM 建構去下載並執行,導致頁面白屏時間變長。解法:加 defer(HTML 解析完才執行)或 async(下載完立刻執行,不等 HTML)。

Q2:什麼是 Critical Rendering Path?
#

首次渲染必須完成的最小路徑:HTML 解析 → CSS 解析 → Render Tree → Layout → Paint。優化 CRP 的目標是讓這條路越短越快,例如:精簡 Critical CSS、延遲非必要 JS、使用 resource hints(preload/preconnect)。

Q3:will-change 有什麼作用?
#

.animated { will-change: transform; }

告訴瀏覽器這個元素即將改變,提前把它提升為獨立的合成層,讓之後的動畫只走 Composite,不觸發 Reflow 和 Repaint。但不要濫用,每個合成層都佔記憶體。