對版面配置位移進行偵錯

瞭解如何找出及修正版面配置位移。

凱蒂漢佩尼斯
Katie Hempenius

本文第一部分探討用於對版面配置位移偵錯的工具,第二部分則討論用於找出版面配置位移原因時的思考流程。

工具

版面配置不穩定 API

Layout Instability API 是測量和回報版面配置位移的瀏覽器機制。所有用於對版面配置位移偵錯的工具 (包括開發人員工具) 最終都是以 Layout Instability API 建構而成。不過,由於靈活彈性,直接使用 Layout Instability API 是功能強大的偵錯工具。

使用方式

用來評估累計版面配置位移 (CLS) 的同一個程式碼片段,也可用於對版面配置位移進行偵錯。下方的程式碼片段會記錄版面配置轉移至控制台的相關資訊。檢查此記錄即可瞭解版面配置位移發生的時間、位置和方式。

let cls = 0;
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

執行這個指令碼時,請注意下列事項:

  • buffered: true 選項代表 PerformanceObserver 應檢查瀏覽器的效能項目緩衝區,找出在觀察器初始化前建立的效能項目。因此,PerformanceObserver 會回報在初始化前後發生的版面配置位移。檢查主控台記錄檔時,請注意這一點。版面配置位移的初始模糊處理可以反映報表待處理作業,而非因多次版面配置位移突然發生。
  • 為了避免影響效能,PerformanceObserver 會等到主要執行緒處於閒置狀態時,回報版面配置位移。因此,視主要執行緒的忙碌程度而定,版面配置的位移與在主控台中記錄時,可能會有短暫的延遲。
  • 這個指令碼會忽略使用者輸入內容在 500 毫秒內發生的版面配置位移,因此不會計入 CLS。

系統會結合使用 LayoutShiftLayoutShiftAttribution 介面,回報版面配置位移的相關資訊。以下各節將詳細說明這些介面。

LayoutShift

每個版面配置位移都會透過 LayoutShift 介面回報。項目的內容如下所示:

duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798

上方項目表示版面配置的位移,導致三個 DOM 元素改變位置。這個特定版面配置位移的版面配置位移分數為 0.175

下列為與版面配置位移偵錯作業最相關的 LayoutShift 例項屬性:

屬性 說明
sources sources 屬性會列出版面配置位移期間移動的 DOM 元素。這個陣列最多可包含五個來源。如果在版面配置位移影響超過五個元素,系統會回報版面配置位移的五大 (評估依據對版面配置穩定性的影響) 來源。這項資訊是透過 LayoutShiftAttribution 介面回報 (詳情請參閱下方說明)。
value value 屬性會回報特定版面配置位移的版面配置位移分數
hadRecentInput hadRecentInput 屬性可指出版面配置的位移是否在使用者輸入內容的 500 毫秒內發生。
startTime startTime 屬性會指出版面配置位移的時間。startTime 表示單位為毫秒,且會根據網頁載入啟動時間進行測量。
duration duration 屬性一律設為 0。這個屬性是繼承自 PerformanceEntry 介面 (LayoutShift 介面會擴充 PerformanceEntry 介面)。不過,時間長度的概念不適用於版面配置位移事件,因此設為 0。如要瞭解 PerformanceEntry 介面,請參閱spec

LayoutShiftAttribution

LayoutShiftAttribution 介面說明單一 DOM 元素的一次移動。如果多個元素在版面配置位移期間移動,sources 屬性會包含多個項目。

舉例來說,下列 JSON 對應了含有一個來源的版面配置位移:<div id='banner'> DOM 元素的從 y: 76 向下移動至 y:246

// ...
  "sources": [
    {
      "node": "div#banner",
      "previousRect": {
        "x": 311,
        "y": 76,
        "width": 4,
        "height": 18,
        "top": 76,
        "right": 315,
        "bottom": 94,
        "left": 311
      },
      "currentRect": {
        "x": 311,
        "y": 246,
        "width": 4,
        "height": 18,
        "top": 246,
        "right": 315,
        "bottom": 264,
        "left": 311
      }
    }
  ]

node 屬性會識別已移動的 HTML 元素。在開發人員工具中將滑鼠遊標懸停在這項屬性上,即可醒目顯示對應的頁面元素。

previousRectcurrentRect 屬性會回報節點的大小和位置。

  • xy 座標會分別回報元素左上角的 x 座標和 y 座標。
  • widthheight 屬性會分別回報元素的寬度和高度。
  • toprightbottomleft 屬性會回報與元素指定邊緣相對應的 x 或 y 座標值。換句話說,top 的值等於 ybottom 的值等於 y+height

如果 previousRect 的所有屬性都設為 0,表示元素已移至檢視畫面。如果 currentRect 的所有屬性都設為 0,表示元素已從檢視畫面中移出。

解讀這些輸出內容時,最需要瞭解的一點是,列為「來源」的元素是在版面配置位移期間轉移的元素。不過,這些元素可能會與版面配置不穩定的「根本原因」間接相關。以下列舉幾個例子。

示例 1

系統會回報這個版面配置位移,內含一個來源:元素 B。不過,這種版面配置位移的根本原因是元素 A 的大小變更。

範例:因元素尺寸變更而造成版面配置位移

示例 2

這個範例中的版面配置位移會回報兩個來源:元素 A 和元素 B。這種版面配置位移的根本原因是元素 A 的位置變更。

範例:因元素位置變更而造成版面配置位移

示例 3

在本例中,版面配置位移會回報一個來源:元素 B。變更元素 B 的位置會導致版面配置位移。

範例:因元素位置變更而造成版面配置位移

示例 4

雖然元素 B 會變更大小,但在本範例中並沒有版面配置位移。

示例:顯示元素變更大小,但未導致版面配置位移的範例

請參閱這個示範影片,瞭解 Layout Instability API 如何回報 DOM 變更情形。

DevTools

效能面板

開發人員工具的「Performance」面板的「Experience」窗格會顯示特定效能追蹤記錄期間的所有版面配置位移,即使版面配置是在使用者互動後 500 毫秒內發生,也不會計入 CLS。將滑鼠遊標懸停在「Experience」面板中的特定版面配置位移,會醒目顯示受影響的 DOM 元素。

螢幕截圖:開發人員工具「Network」面板中顯示的版面配置位移

如要進一步瞭解版面配置位移,請按一下版面配置位移,然後開啟「Summary」導覽匣。系統會使用 [width, height] 格式列出元素尺寸的變更,請使用 [x,y] 格式列出元素位置的變更。「HadRecent input」屬性可指出版面配置的位移是否在使用者互動後 500 毫秒內發生。

開發人員工具「摘要」分頁的版面配置位移螢幕截圖

如要瞭解版面配置位移的持續時間,請開啟「Event Log」(事件記錄) 分頁標籤。您也可以透過在「Experience」窗格中查看紅色版面配置位移矩形的長度,大致瞭解版面配置位移的持續時間。

開發人員工具的「事件記錄」分頁螢幕截圖

如要進一步瞭解如何使用「Performance」面板,請參閱「效能分析參考資料」。

醒目顯示版面配置位移區域

強調版面配置位移區域是一項實用技巧,可讓您快速且快速地掌握網頁上的版面配置位移位置和時間。

如要在開發人員工具中啟用版面配置位移區域,請依序前往「Settings」>「More Tools」>「Rendering」>「Layout Shift Regions」,然後重新整理要偵錯的網頁。版面配置位移的區域會以紫色快速醒目顯示。

找出版面配置位移原因的思維程序

無論版面配置位移的時間或方式為何,您都可以按照下列步驟找出版面配置位移的原因。這些步驟可以利用執行 Lighthouse 來補充,但請注意,Lighthouse 只能識別初始頁面載入期間發生的版面配置位移。此外,Lighthouse 也可以只針對版面配置位移的某些原因 (例如沒有明確寬度和高度的圖片元素) 提供建議。

找出版面配置位移的原因

下列事件可能會導致版面配置位移:

  • DOM 元素位置變更
  • DOM 元素的維度變更
  • 插入或移除 DOM 元素
  • 觸發版面配置的動畫

特別是,移動的元素前的 DOM 元素是最有可能涉及「造成」版面配置位移的元素。因此,在調查版面配置位移發生的原因時,請考慮以下幾點:

  • 上述元素的位置或尺寸是否改變?
  • 經過移動的元素之前,是否已插入或移除 DOM 元素?
  • 已移動元素的位置是否明確變更?

如果上述元素沒有造成版面配置位移,請考慮其他前後元素來繼續搜尋。

此外,版面配置位移的方向和距離也能提供根本原因的提示。舉例來說,較大的向下移通常代表插入 DOM 元素,而 1 px 或 2 像素的版面配置位移通常表示套用了衝突的 CSS 樣式,或載入與套用網站字型的應用程式。

這張圖表顯示字型交換造成的版面配置位移
在這個範例中,字型交換造成網頁元素向上移動 5 像素。

以下是最常導致版面配置位移事件的一些特定行為:

變更元素的位置 (非因移動其他元素而造成)

這類變更通常源自於:

  • 延遲載入或覆寫先前宣告的樣式。
  • 動畫和轉場效果。

元素尺寸變更

這類變更通常源自於:

  • 延遲載入或覆寫先前宣告的樣式。
  • 不含 widthheight 屬性的圖片和 iframe,會在「版位」轉譯後載入。
  • 不含 widthheight 屬性的文字區塊,會在轉譯文字後交換字型。

插入或移除 DOM 元素

原因通常是:

  • 插入廣告和其他第三方嵌入內容。
  • 插入橫幅、快訊和視窗。
  • 會在現有內容上方載入額外內容的無限捲動和其他使用者體驗模式。

觸發版面配置的動畫

部分動畫效果可以觸發版面配置。常見的例子是, DOM 元素是透過遞增 topleft 等屬性的方式「動畫」,而不是使用 CSS 的 transform 屬性。詳情請參閱「如何建立高效能的 CSS 動畫」一文。

重現版面配置位移

您無法修正無法重現的版面配置位移。如要深入瞭解網站版面配置的穩定性,最簡單有效的方法之一是需要 5 至 10 分鐘與網站互動,目標是觸發版面配置位移。執行這項作業時,請將主控台保持開啟,並使用 Layout Instability API 回報版面配置位移。

為難以找出版面配置位移,建議您使用不同裝置和連線速度重複這項練習。具體來說,連線速度越慢,越容易找出版面配置位移。此外,您也可以使用 debugger 陳述式,更輕鬆逐步完成版面配置位移。

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      debugger;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

最後,如果版面配置的問題無法在開發過程中重現,請考慮將 Layout Instability API 與選用的前端記錄工具搭配使用,以便收集這些問題的更多資訊。請參閱如何追蹤網頁上最大位移元素的程式碼範例