CLS 意思是什麼:版面位移的計算公式、評分標準與診斷方式
陳柏翰
網站效能工程師
CLS 是什麼:量化版面跳動的核心指標
你在 PageSpeed Insights 看到 CLS 0.28,然後想搞清楚這個數字代表什麼。CLS(Cumulative Layout Shift,累積版面位移)是 Google Core Web Vitals 三大指標之一,用來量化網頁載入過程中,使用者沒有預期到的版面跳動程度。
CLS 是 Core Web Vitals 三大指標之一。如果尚未熟悉 LCP、INP、CLS 各自量的是什麼,建議先看一下三個指標的完整定義。
具體來說:使用者正在閱讀一段文字,廣告突然從上方插入,整個內容向下跳了一截,這就是 CLS 要捕捉的體驗問題。LCP 測的是「頁面什麼時候載完」,INP 測的是「互動回應有多快」,而 CLS 測的是「頁面穩不穩定、會不會突然跳動」。
CLS 的值沒有單位,是一個純數字。0 代表完全沒有位移,數字越高代表版面越不穩。Google 建議通過門檻是 0.1 以下。
版面位移什麼時候算「非預期」
並不是所有版面移動都算 CLS。使用者主動觸發的移動不算。比如你點了「展開更多」按鈕,內容往下撐開,這是預期行為,不計入 CLS。但如果頁面載入 2 秒後廣告突然出現,把你正在閱讀的文章往下推,那就是非預期的版面位移,會被計入。
Google 的定義是:版面位移發生在使用者輸入操作(點擊、觸碰、鍵盤輸入)後的 500ms 內,才算是「使用者預期」的移動,不計入 CLS。超過 500ms 才發生的移動,一律視為非預期。
Session window 累積方式(2021 年更新)
很多文章的 CLS 解釋已經過時了,說的是「把所有版面位移加總起來」。Google 在 2021 年底改了計算方式,現在用的是 session window aggregation。
運作方式:把連續的版面位移事件分組成「session window」,每個 window 最長 5 秒、各事件間隔不超過 1 秒。CLS 取的是所有 session window 中位移分數總和最高的那一個。這個更新的目的是讓長時間瀏覽的頁面(像新聞網站、SPA)不會因為正常的頁面更新而累積超高的 CLS。換句話說,如果你的頁面每隔 10 秒就有一個小位移,在新算法下不會把它們加在一起。
CLS 分數怎麼算:impact fraction × distance fraction
每次版面位移的分數由兩個因子相乘決定:版面位移分數 = impact fraction × distance fraction。這個公式的設計邏輯是同時懲罰「大面積移動」和「移動距離遠」這兩種情況。
Impact fraction:位移元素佔了多少視口
Impact fraction 是受版面位移影響的視口面積比例。計算方式:把所有移動元素在位移前和位移後的位置合集,除以視口總面積。例如,一個元素佔了視口 50% 的高度,它向下移動到佔了視口 75% 的位置,那 impact fraction 就是 0.75(取移動前後的聯集面積)。
Distance fraction:位移了多遠
Distance fraction 是元素移動距離相對於視口尺寸的比例。取的是移動距離除以視口較長的邊(通常是高度)。一個元素在 800px 高的視口中移動了 200px,distance fraction 就是 0.25。
為什麼這個公式能反映「使用者體驗有多差」
兩個因子相乘的設計是刻意的。只移動了一小個角落元素,impact fraction 很低,分數不高。移動距離很短,distance fraction 也低。但如果一個大 banner 在視口中央往下跳了一大截,兩個因子都高,分數就會很難看。這對應的是真實的體驗問題嚴重程度。
以具體數字舉例:一個元素的 impact fraction 是 0.5,distance fraction 是 0.3,那這次位移的分數是 0.5 × 0.3 = 0.15。根據 Google 官方 CLS 定義與計算說明,CLS 的最終數值是對應 session window 內所有這類分數的總和。
CLS 評分標準
Google 定義的三段評分,以網頁所有使用者載入體驗的 75th percentile 為準:
| 等級 | CLS 分數 | Google 評定 |
|---|---|---|
| 優(Good) | ≤ 0.1 | 通過 |
| 待改善(Needs Improvement) | 0.1 — 0.25 | 需要處理 |
| 差(Poor) | > 0.25 | 嚴重問題 |
75th percentile 的意思是:取你的頁面所有真實使用者的 CLS 數值,排序後看第 75 個百分位的數字。這代表至少 75% 的使用者體驗要達到對應等級。Google 不是看平均值,而是看「最差的那四分之一使用者體驗到什麼」。
為什麼不用平均值?因為平均值容易被少數極端值拉高或拉低。如果你的頁面對 90% 的使用者是 CLS 0.05,但對 10% 的使用者(通常是慢網路或特定裝置)是 0.9,平均值還是看起來不錯,但 P75 就會反映出那 25% 的差體驗。
造成 CLS 高的四大常見原因
跑完 Lighthouse 看到 CLS 0.25,下一步是找是哪個元素在跳動。這四類是最常見的來源:
- 未定義尺寸的圖片與影片:沒有 width/height 屬性的 <img> 或 <video>,瀏覽器不知道要預留多少空間,圖片載入後就會把下方內容往下推。這是最常見也最好修的 CLS 原因,圖片 CLS 修復的完整方法可以找到具體步驟和 before/after 數據。
- 動態注入的廣告和嵌入內容:AdSense、第三方 widget、社群嵌入。這些在頁面初始渲染後才載入,如果沒有預先為容器保留空間,它們出現的瞬間就會把內容推開。
- 自定義字體 FOIT/FOUT:FOIT(Flash of Invisible Text)和 FOUT(Flash of Unstyled Text)都可能造成版面位移。字體載入前後如果字元寬度不同,整個段落的排版都會跳動。font-display 設定直接影響 CLS。
- 非 transform/opacity 的 CSS 動畫:用 top、left、margin 做的動畫會觸發 layout reflow,算 CLS。這和下面要解釋的 compositor thread 有關係。
每一類的具體修法都有對應的深度文章。這裡只說原因和方向,不展開每種實作細節。(詳見 圖片優化對 LCP 和 CLS 的影響)
為什麼 transform 動畫不算 CLS
用 transform: translateY() 做的動畫不會觸發 CLS,而 top: 100px 動畫會,原因在 browser rendering pipeline 的架構層面。
top/left 的變更需要走完整的 layout → paint → composite 流程,瀏覽器要重新計算所有受影響元素的位置。transform 在 compositor thread 上執行,完全繞過 layout 和 paint 階段,不改變元素在 document flow 中的幾何位置,所以 Layout Instability API 不會記錄它為版面位移。這是 GPU 加速動畫的核心原理之一。
怎麼診斷 CLS:工具選擇和診斷順序
Lighthouse 是最快的起點,但 CLS 的診斷需要工具組合,因為 lab data 和 field data 之間常常有很大的落差。
Lighthouse 看 CLS:快速掃描,但有一個重要盲點
Lighthouse 是在受控環境下做單次模擬載入。它能抓到靜態資源造成的 CLS(未設尺寸的圖片、字體 FOUT),但有個根本性的限制:Lighthouse 不執行廣告請求、不觸發 A/B testing scripts、不載入需要用戶行為才啟動的第三方 widget。這些延遲注入的動態內容在 Lighthouse 裡根本不出現,所以 Lighthouse CLS 是 0 但真實用戶看到的是 Poor 這件事相當常見。
Chrome DevTools Performance 面板:找到具體的罪魁禍首
要知道是哪個元素在跳動,開 DevTools → Performance 面板 → 錄製頁面載入。在時間軸上找紅色的「Layout Shift」標記,點進去可以看 Sources 欄位,列出觸發這次位移的 DOM 元素。這比看 Lighthouse 報告更直接,但需要手動錄製和分析。
PageSpeed Insights vs CrUX:為什麼數字不一樣
PageSpeed Insights(PSI)頂部顯示的「Field Data」來自 Chrome User Experience Report(CrUX),是過去 28 天真實 Chrome 用戶的數據。底部的「Lab Data」才是 Lighthouse 的模擬結果。
如果你看到 Lab Data CLS 是 0.02 但 Field Data 顯示 Poor,代表真實用戶看到的版面跳動比模擬環境嚴重很多。可能的原因:廣告在真實環境載入但 Lighthouse 不載入、慢網路用戶圖片載得更慢所以跳動更明顯、或是登入狀態下有不同的 layout。
還有一個坑:CrUX 數據需要至少一定量的真實訪問才會有數據。新網站或低流量頁面可能在 PSI 上看不到 Field Data,這時只能依賴 Lab Data。根據 Google 建議的 CLS 優化做法,這種情況下建議在真實設備上用 Chrome 手動測試,而不是只靠 Lighthouse。
修 CLS 的核心方向
每種修法都有對應的技術細節,這裡只說原理和方向:
- 為圖片和影片預留空間:在 HTML 中加 width 和 height 屬性,或用 CSS
aspect-ratio保留比例空間,讓瀏覽器在圖片載入前就知道要佔多少版面。這是成本最低、效果最穩的修法。 - 廣告與第三方嵌入用 min-height 容器:在廣告載入前先放一個有最小高度的容器佔位,廣告出現後不會因為空間從 0 變成 200px 而擠壓其他內容。
- 字體用 font-display: optional:比 swap 更保守:如果字體沒在第一個 render frame 內載完,就永遠用 fallback 字體,完全避免 FOUT。代價是偶爾顯示 fallback 字體,但 CLS 最穩定。
- Skeleton UI:與其讓頁面在內容載完後「突然出現」,不如先渲染一個骨架結構佔住版面位置,內容載完後平滑替換,版面尺寸不改變。
每個方向的深度實作(程式碼、邊緣案例、平台差異)在各自的子文章有完整說明。這個系列涵蓋了從LCP 優化到 CLS 修復的完整流程。
我拿過一個電商首頁做過實測。原始 CLS 是 0.28(Poor),問題點集中在兩個地方:hero banner 的圖片沒設 width/height、Google Ads 容器沒有 min-height。光是補上這兩個屬性,CrUX 數據在下個 28 天週期就降到 0.07(Good)。沒動任何 JavaScript,沒改 CSS 架構。
| 修改項目 | 修改前 CLS | 修改後 CLS |
|---|---|---|
| hero banner 加 width/height 屬性 | 0.28 | 0.14 |
| 廣告容器加 min-height: 250px | 0.14 | 0.07 |
CLS 和 SEO 排名的關係
CLS 是 Google Page Experience signal 的一部分,和 LCP、INP 一起構成 Core Web Vitals。Google 確認 Core Web Vitals 是排名因素,但它是 tiebreaker 層級的信號。
實際意思是:如果兩篇文章在內容相關性和其他主要排名因素上差不多,CLS 較好的那篇有優勢。但 CLS 不會讓一篇內容薄弱的文章排過內容更好的競品。
直接影響轉換率的部分更值得重視。CLS 0.25 的頁面上,使用者要點一個按鈕,但在他點下去的瞬間廣告插入讓按鈕移位,結果誤觸了廣告,這種體驗直接影響的是跳出率和完成操作的比率,不只是排名。Google 的研究顯示,頁面 CLS 從 Poor 改善到 Good 的網站,表單送出率和購買轉換率都有明顯提升,幅度比同期的單純 SEO 調整更顯著。
DOM 渲染效率同時影響 CLS 和 INP 的顯示延遲。INP 優化的診斷與修復方法涵蓋了 content-visibility 和 DOM size 優化對 presentation delay 的具體改善效果。
常見問題
CLS 意思是什麼,中文怎麼翻?
CLS 是 Cumulative Layout Shift 的縮寫,中文翻譯是累積版面位移。是 Google Core Web Vitals 三大指標之一,量化網頁載入時非預期的版面跳動程度。
CLS 0.1 代表什麼?是好是壞?
剛好在及格線上。Google 的評分是:0.1 以下為 Good(通過),0.1 到 0.25 為 Needs Improvement,超過 0.25 為 Poor。CLS 0.1 表示你的頁面勉強達標,建議繼續優化到 0.05 以下會更穩。
CLS 和 LCP、INP 有什麼關係?
三個都是 Core Web Vitals 的構成指標,但量的是完全不同的體驗維度。LCP(Largest Contentful Paint)量的是最大內容元素什麼時候顯示,量的是速度。INP(Interaction to Next Paint)量的是互動回應延遲,量的是流暢度。CLS 量的是版面穩定性,即非預期跳動的程度。三個同時要過才算完整通過 Core Web Vitals。
我的 Lighthouse CLS 是 0,但 PageSpeed Insights 顯示 Poor,為什麼?
Lighthouse 是在模擬環境做單次測試,不執行廣告請求,也不觸發需要用戶互動才啟動的第三方 script。PageSpeed Insights 的 Field Data 來自真實 Chrome 用戶的實際體驗。常見原因:廣告在真實環境延遲載入後插入版面、特定裝置或網路速度讓圖片載入變慢造成更大的位移。用 Chrome DevTools Performance 面板錄製真實載入過程,找到觸發位移的具體元素。
CLS 計算公式是什麼?
每次版面位移的分數 = impact fraction × distance fraction。Impact fraction 是受位移影響的視口面積比例,distance fraction 是移動距離相對視口尺寸的比例。CLS 最終值取所有 session window 中分數最高的那一個 window 的累計總和。
廣告會造成 CLS 嗎?怎麼避免?
會,而且是最難完全消除的 CLS 來源。廣告的高度在競標完成前通常不確定,如果廣告位置沒有預留固定空間,廣告出現時就會推動周圍內容。基本做法:為廣告容器設定 min-height,讓版面在廣告載入前就佔有空間。但如果廣告高度可能超過 min-height,位移仍然存在。
修好 CLS 之後,Google 排名會馬上改善嗎?
不會馬上。CrUX 數據每 28 天更新一次,Google 的排名信號也有延遲。修完 CLS 後通常要等 4 到 6 週,PageSpeed Insights 的 Field Data 才會反映改善。排名變化的時間更難預測,因為 CWV 是 tiebreaker 層級的信號,整體影響也取決於你和競品的差距。
怎麼用 Chrome DevTools 找到造成 CLS 的元素?
打開 DevTools → Performance 標籤 → 點錄製 → 重新載入頁面 → 停止錄製。在時間軸上找紅色標記的「Layout Shift」事件,點擊後在下方的 Summary 或 Details 面板可以看到觸發位移的 DOM 元素列表。每次位移的 score、impact fraction、distance fraction 都會列出來。