過去,網頁程式開發人員必須評估網頁中主要內容載入後,使用者能看到的頁面主要內容有多快。較舊的指標 (例如 load 或 DOMContentLoaded) 不一定能對應到使用者看到的畫面,因此效果不佳。此外,以使用者為中心的成效指標 (例如最初內容繪製 (FCP)) 只會擷取載入體驗的起點。如果網頁顯示啟動畫面或顯示載入指標,則表示這個時刻與使用者的關聯性並不高。
過去,我們推薦了首次有效繪製 (FMP) 和速度指數 (SI) 等成效指標,以便擷取初次繪製後更豐富的載入體驗,但這些指標過於複雜、難以解釋,且經常錯誤;也就是說,網頁主要內容載入後,系統仍無法辨識這些內容。
根據 W3C 網頁效能工作小組的討論和 Google 的研究結果,我們發現,如要更準確地評估網頁載入主要內容的時間,就必須檢查顯示最大元素的時間。
什麼是 LCP?
LCP 會回報可視區域中最大圖片、文字區塊或影片的顯示時間 (相對於使用者首次瀏覽至相應頁面的時間)。
良好的 LCP 分數應如何?
為了提供良好的使用者體驗,網站應盡量使用 2.5 秒以內的最大內容繪製功能。為確保您大多數的使用者都能達成此目標,評估頁面載入內容的第 75 個百分位數,是針對行動裝置和電腦裝置的區隔,理想的評估門檻。
考量的要素
如同「Largest Contentful Paint」中目前所述 API,也就是元素的類型 「最大內容繪製」的標準如下:
<img>
元素 (第一個影格顯示時間會用於動畫內容,例如 GIF 或 PNG 動畫)<svg>
元素中的<image>
元素<video>
元素 (使用的代表圖片載入時間或影片的第一個影格顯示時間,以較早者為準)- 使用
url()
函式載入背景圖片的元素 (而非 CSS 漸層) - 區塊層級元素包含文字節點或其他內嵌層級文字元素子項。
請注意,為了簡化開頭,將元素限制於此有限集合,是刻意的設定。隨著更多研究進行,未來可能會新增其他元素 (例如完整的 <svg>
支援)。
LCP 評估除了考量部分元素外,也會運用經驗法則,排除使用者可能會認為「沒有內容」的特定元素。如果是以 Chromium 為基礎的瀏覽器,則包括:
- 不透明度為 0 的元素,使用者看不到
- 覆蓋整個可視區域的元素,系統有可能視為背景,而非內容
- 預留位置圖片或其他含有較低熵的圖片,但可能無法反映網頁的實際內容
瀏覽器可能會繼續改進這些經驗法則,確保我們符合使用者對於最大 contentful 元素的期望。
這些「內容」經驗法則可能與首次顯示內容所需時間 (FCP) 所用的概念不同,後者可能會考量上述部分元素,例如預留位置圖片或完整可視區域圖片 (即使這些元素不符合 LCP 資格)。儘管兩者都使用「contentful」但指標目的就不一樣。FCP 會測量在畫面和 LCP 顯示「任何內容」的時機,並在顯示「主要內容」時評估 LCP,藉此更謹慎。
元素大小的決定方式
LCP 會回報的元素大小,通常是使用者可以在可視區域中看到的大小。如果元素超出可視區域,或者有任何元素遭到裁剪或出現不可見的溢位,這些部分就不會計入元素的大小。
如果圖片元素是從內建大小調整大小,回報的大小即為顯示大小或內建函式大小,以較小者為準。
如果是文字元素,LCP 只會考慮可包含所有文字節點的最小矩形。
對於所有元素,LCP 不會考量使用 CSS 套用的邊界、邊框間距或邊框,
LCP 會何時回報?
網頁通常會分階段載入,因此網頁中最大的元素可能會改變。
為了因應這類變更,瀏覽器會在瀏覽器繪製第一個影格時,分派 largest-contentful-paint
類型的 PerformanceEntry
,識別最大的內容元素。但在轉譯後續影格後,只要內容元素最大的變更,就會分派另一個 PerformanceEntry
。
舉例來說,如果網頁上有文字和主頁橫幅,瀏覽器一開始只會轉譯文字,這時瀏覽器就會分派 element
屬性可能參照 <p>
或 <h1>
的 largest-contentful-paint
項目。主頁橫幅載入完成後,系統會分派第二個 largest-contentful-paint
項目,其 element
屬性會參照 <img>
。
元素算繪完成並向使用者顯示後,才能視為最大的內容元素。尚未載入的圖片不會視為「已顯示」。兩者都是在字型區塊期間使用網路字型的文字節點。在這種情況下,系統可能會將較小的元素回報為最大的內容元素,但大型元素完成轉譯後,就會建立另一個 PerformanceEntry
。
除了延遲載入圖片和字型之外,當有新內容出現時,網頁可能會在 DOM 加入新的元素。如果這些新元素大於前一個最大內容元素,則系統也會回報新的 PerformanceEntry
。
如果最大內容元素已從可視區域或甚至 DOM 中移除,則除非算繪較大的元素,否則此元素仍會是最大的內容元素。
當使用者與網頁互動 (透過輕觸、捲動或按下按鍵) 後,瀏覽器就會停止回報新項目,因為使用者互動經常會改變使用者能夠看到的內容 (尤其是捲動網頁時的情況更是如此)。
為了進行分析,請只將最近派出的PerformanceEntry
回報給數據分析服務。
載入時間與轉譯時間
基於安全考量,系統不會針對缺少 Timing-Allow-Origin
標頭的跨來源圖片揭露圖片的轉譯時間戳記。反之,系統只會顯示載入時間 (因為許多其他網路 API 都已經公開該資訊)。
這可能導致在看似不可能的情況下,網頁 API 回報 LCP 的時間比 FCP 早。雖然情況不同,但只會在有這項安全性限制的情況下出現。
建議盡可能設定 Timing-Allow-Origin
標頭,提升指標的準確度。
如何處理元素版面配置和大小的變更?
為了讓系統計算和分派新效能項目時的效能負擔較低,即使變更元素的大小或位置,系統也不會產生新的 LCP 候選項目。系統只會考量元素的初始大小和可視區域中的位置。
也就是說,系統可能不會回報一開始在畫面外轉譯,之後才在螢幕上顯示的圖片。這也意味著元素一開始在可視區域顯示,然後被向下推,而在檢視區外,依然會報告其初始在可視區域內的大小。
範例
以下列舉幾個熱門網站出現最大內容繪製的情形:
![cnn.com 提供的最大內容繪製時間表](https://web.dev/static/articles/lcp/image/largest-contentful-paint-fc43128e011aa.png?authuser=1&hl=zh-tw)
![techcrunch.com 的最大內容繪製時間軸](https://web.dev/static/articles/lcp/image/largest-contentful-paint-3713e2f14970a.png?authuser=1&hl=zh-tw)
在上方兩個時間軸中,載入內容的最大元素會隨著內容變化。在第一個範例中,系統會將新內容加入 DOM,並變更最大的元素。在第二個範例中,版面配置會變更,先前最大的內容則會從可視區域中移除。
雖然延遲載入內容通常比網頁上現有的內容更大,但實際上並不一定是如此。接下來的兩個例子呈現了 LCP 在網頁完全載入前發生的情況。
![instagram.com 提供的最大內容繪製時間軸](https://web.dev/static/articles/lcp/image/largest-contentful-paint-9bc403e812154.png?authuser=1&hl=zh-tw)
![google.com 上最大的內容繪製時間軸](https://web.dev/static/articles/lcp/image/largest-contentful-paint-6c5554de0eac7.png?authuser=1&hl=zh-tw)
在第一個範例中,Instagram 標誌的載入時間相對較早,即使其他內容不斷顯示,仍然會是最大的元素。在 Google 搜尋結果網頁的範例中,最大的元素是指圖片或標誌載入完成前顯示的一段文字,由於所有個別圖片都小於這個段落,因此圖片在整個載入程序中仍是最大的元素。
如何評估 LCP
您可以從研究室或實際操作中評估 LCP,以下工具也有提供這項指標:
現場工具
研究室工具
在 JavaScript 中評估 LCP
如要評估 JavaScript 中的 LCP,您可以使用 Largest Contentful Paint API。以下範例說明如何建立 PerformanceObserver
來監聽 largest-contentful-paint
項目,並將這些項目記錄到控制台。
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
在上述範例中,每個記錄的 largest-contentful-paint
項目都代表目前的 LCP 候選人。一般來說,最後一個發出的項目 startTime
值是 LCP 值,但不一定每次都會發生此值。並非所有 largest-contentful-paint
項目都可用於測量 LCP。
下節將說明 API 報表與指標計算方式之間的差異。
指標和 API 之間的差異
- API 會分派在背景分頁中載入的
largest-contentful-paint
項目,但計算 LCP 時,請忽略這些網頁。 - API 會在網頁於背景運作後繼續分派
largest-contentful-paint
項目,但在計算 LCP 時,請忽略這些項目 (只有在網頁在整個前景中都處於前景時,才會考慮元素)。 - 當網頁透過往返快取還原時,API 不會回報
largest-contentful-paint
項目,但應在這類情況下評估 LCP,因為使用者只會將這些項目視為不同網頁造訪。 - API 不會考量 iframe 內的元素,但指標是網頁使用者體驗的一部分。如果網頁含有 iframe 的 LCP (例如內嵌影片上的代表圖片),這會顯示為 CrUX 和 RUM 之間的差異。若要正確評估 LCP,請考量其情況。子頁框可以使用 API 向父項頁框回報
largest-contentful-paint
項目以進行匯總。 - 這個 API 會從導覽開始評估 LCP,但針對預先算繪的網頁的 LCP 應從
activationStart
評估,因為後者會對應到使用者完成的 LCP 時間。
開發人員可以透過 web-vitals
JavaScript 程式庫評估 LCP 差異,而與其記住這些細微差異,後者會盡可能為您處理這些差異 (請注意,不包含 iframe 的問題):
import {onLCP} from 'web-vitals';
// Measure and log LCP as soon as it's available.
onLCP(console.log);
如需在 JavaScript 中評估 LCP 的完整範例,請參閱 onLCP()
的原始碼。
如果最大元素不是最重要的元素,該怎麼辦?
在某些情況下,網頁上最重要的元素 (或元素) 與最大的元素不同,因此開發人員可能較有興趣測量其他元素的顯示時間。方法是使用 Element Timing API,詳情請參閱自訂指標相關文章。
如何改善 LCP
請參閱最佳化 LCP 的完整指南,瞭解如何辨識領域的 LCP 時間,並運用研究室資料深入瞭解及最佳化這些時間。
其他資源
- Annie Sullivan 於 performance.now() 分享的Chrome 效能監控經驗談 (2019)
變更記錄
有時用於測量指標的 API 中會發現錯誤,有時在指標本身的定義中也會發現錯誤。因此,有時需要進行變更,這些變更可能會在內部報表和資訊主頁中顯示為改善或迴歸。
為方便您管理,這些指標導入或定義的所有變更都會顯示在這份變更記錄中。
如果對這些指標有任何意見,歡迎透過 web-vitals-feedback Google 群組提供。