发布时间:2019 年 8 月 8 日,最后更新时间:2025 年 3 月 20 日
最大内容ful Paint (LCP) 是一项重要的稳定Core Web Vitals指标,用于衡量感知加载速度,因为它标记了页面加载时间轴中的一个点,在该点,页面的主要内容可能已加载完成 - 快速的 LCP 有助于让用户确信页面是有用的。
从历史上看,Web 开发人员一直难以衡量网页主要内容加载并对用户可见的速度。较旧的指标(如load或DOMContentLoaded)效果不佳,因为它们不一定与用户在其屏幕上看到的内容相对应。而较新的、以用户为中心的性能指标,如首次内容ful Paint (FCP),仅捕获加载体验的开始。如果页面显示启动画面或加载指示器,则此时刻与用户无关。
过去,我们推荐了First Meaningful Paint (FMP)和Speed Index (SI)(两者在 Lighthouse 中都可用)等性能指标,以帮助捕获初始绘制后更多的加载体验,但这些指标很复杂、难以解释且常常出错 - 这意味着它们仍然无法识别页面主要内容何时加载。
基于W3C Web Performance Working Group中的讨论以及 Google 进行的研究,我们发现,衡量页面主要内容何时加载的更准确方法是查看渲染最大元素的时间。
什么是 LCP?
LCP 报告在视口中可见的最大图像、文本块或视频的渲染时间,相对于用户首次导航到页面的时间。
什么是良好的 LCP 分数?
为了提供良好的用户体验,网站应力争使 Largest Contentful Paint 达到 2.5 秒 或更短。为了确保您为大多数用户实现了此目标,一个好的衡量阈值是页面加载的 第 75 百分位数,按移动设备和桌面设备细分。
要了解有关此建议背后的研究和方法的更多信息,请参阅:定义 Core Web Vitals 指标阈值。
哪些元素被考虑在内?
如Largest Contentful Paint API中所指定,针对 Largest Contentful Paint 考虑的元素类型为
<img>
元素(首帧呈现时间用于动画内容,例如 GIF 或动画 PNG)<svg>
元素内的<image>
元素<video>
元素(海报图像加载时间或视频的首帧呈现时间 - 以较早者为准)- 使用
url()
函数加载的背景图像的元素(与 CSS 渐变相反) - 包含文本节点或其他内联级别文本元素子级的块级元素。
请注意,将元素限制为此有限的集合是故意的,目的是降低复杂性。随着更多研究的进行,将来可能会添加其他元素(例如完整的 <svg>
支持)。
除了仅考虑某些元素外,LCP 测量还使用启发式方法排除用户可能视为“非内容ful”的某些元素。对于基于 Chromium 的浏览器,这些包括
- 不透明度为 0 的元素,即用户不可见的元素
- 覆盖整个视口的元素,可能被视为背景而不是内容
- 占位符图像或其他低熵图像,可能无法反映页面的真实内容
浏览器可能会继续改进这些启发式方法,以确保我们符合用户对最大内容ful元素的期望。
这些“内容ful”启发式方法可能与首次内容ful Paint (FCP)使用的启发式方法不同,FCP 可能会考虑其中一些元素,例如占位符图像或全视口图像,即使它们不符合 LCP 候选者的条件。尽管两者都在名称中使用了“内容ful”,但这些指标的目标是不同的。FCP 衡量任何内容何时绘制到屏幕上,而 LCP 衡量主要内容何时绘制,因此 LCP 旨在更具选择性。
如何确定元素的大小?
为 LCP 报告的元素大小通常是在视口中对用户可见的大小。如果元素延伸到视口之外,或者元素的任何部分被剪切或具有不可见的溢出,则这些部分不计入元素的大小。
对于已从其固有大小调整大小的图像元素,报告的大小是可见大小或固有大小,以较小者为准。
对于文本元素,LCP 仅考虑可以包含所有文本节点的最小矩形。
对于所有元素,LCP 不考虑使用 CSS 应用的边距、内边距或边框。
何时报告 LCP?
网页通常分阶段加载,因此,页面上最大的元素可能会发生变化。
为了处理这种潜在的变化,浏览器会在浏览器绘制第一帧后立即调度类型为 largest-contentful-paint
的 PerformanceEntry
,以标识最大的内容ful元素。但是,在渲染后续帧后,只要最大的内容ful元素发生变化,它将调度另一个 PerformanceEntry
。
例如,在具有文本和主打图片的页面上,浏览器最初可能只渲染文本 - 此时浏览器将调度 largest-contentful-paint
条目,其 element
属性可能引用 <p>
或 <h1>
。稍后,一旦主打图片完成加载,将调度第二个 largest-contentful-paint
条目,并且其 element
属性将引用 <img>
。
只有在元素渲染并对用户可见后,才能将其视为最大的内容ful元素。尚未加载的图像不被视为“已渲染”。在字体阻止期内使用 Web 字体的文本节点也不被视为“已渲染”。在这种情况下,可能会将较小的元素报告为最大的内容ful元素,但一旦较大的元素完成渲染,就会创建另一个 PerformanceEntry
。
除了延迟加载的图像和字体外,页面可能会在新内容可用时向 DOM 添加新元素。如果任何这些新元素大于先前的最大内容ful元素,也将报告新的 PerformanceEntry
。
如果最大的内容ful元素从视口中移除,甚至从 DOM 中移除,它仍然是最大的内容ful元素,除非渲染了更大的元素。
一旦用户与页面交互(通过点击、滚动或按键),浏览器将停止报告新条目,因为用户交互通常会更改用户可见的内容(滚动尤其如此)。
为了进行分析,您应该仅将最近调度的 PerformanceEntry
报告给您的分析服务。
加载时间与渲染时间
出于安全原因,图像的渲染时间戳最初未针对缺少 Timing-Allow-Origin
标头的跨域图像公开。相反,仅公开了它们的加载时间(因为这已通过许多其他 Web API 公开)。
加载时间通常会略晚于资源下载结束时间(Resource Timing 中的 responseEnd
),因为即使在开始渲染资源之前,浏览器也需要时间在下载完成后处理资源。但是,如果 LCP 资源已预加载或渲染延迟,则加载时间和渲染时间之间可能会存在更大的差距。
这可能会导致看似不可能的情况,即 Web API 报告的 LCP 早于 FCP。事实并非如此,只是由于此安全限制而显得如此。
这个问题已于 2024 年底得到解决,并且即使未提供 Timing-Allow-Origin
,也从 Chrome 133 开始提供稍微粗略的渲染时间。
如果可能,仍然建议设置 Timing-Allow-Origin
标头,以便您的指标更准确,尤其是对于不包含此最新更改的浏览器。
如何处理元素布局和大小更改?
为了保持计算和调度新性能条目的性能开销较低,元素大小或位置的更改不会生成新的 LCP 候选者。仅考虑元素在视口中的初始大小和位置。
这意味着最初在屏幕外渲染,然后过渡到屏幕上的图像可能不会被报告。这也意味着最初在视口中渲染,然后被向下推到视图之外的元素仍将报告其初始视口内大小。
示例
以下是一些在几个热门网站上发生 Largest Contentful Paint 的示例


在这两个时间线中,最大元素都随着内容的加载而变化。在第一个示例中,新内容被添加到 DOM,这改变了哪个元素是最大的。在第二个示例中,布局发生变化,之前最大的内容从视口中移除。
虽然通常情况下,延迟加载的内容比页面上已有的内容更大,但情况并非总是如此。接下来的两个示例显示 LCP 在页面完全加载之前发生。

在此示例中,Instagram 徽标加载相对较早,即使其他内容逐渐显示,它仍然是最大的元素。

在此 Google 搜索结果页面示例中,最大的元素是一段文本,该文本在任何图像或徽标完成加载之前显示。由于所有单个图像都小于此段文本,因此它在整个加载过程中仍然是最大的元素。
如何衡量 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 内的元素,但指标会考虑,因为它们是页面用户体验的一部分。在 LCP 位于 iframe 中的页面(例如,嵌入视频上的海报图像)中,这将显示为 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);
请参阅 onLCP()
的源代码,以获取如何在 JavaScript 中测量 LCP 的完整示例。
如果最大的元素不是最重要的元素怎么办?
在某些情况下,页面上最重要的元素(或多个元素)与最大的元素不同,开发者可能更感兴趣的是测量这些其他元素的渲染时间。这可以使用 Element Timing API 实现,如关于 自定义指标 的文章中所述。
如何改进 LCP
优化 LCP 的完整指南可帮助您了解在实际应用中识别 LCP 时间,并使用实验室数据深入分析和优化它们的过程。
其他资源
- 从 Chrome 中的性能监控中吸取的教训,Annie Sullivan 在 performance.now() (2019) 的演讲。
更新日志
有时,在用于衡量指标的 API 中会发现错误,有时在指标本身的定义中也会发现错误。因此,有时必须进行更改,这些更改可能会在您的内部报告和仪表板中显示为改进或倒退。
为了帮助您管理这一点,对这些指标的实现或定义的所有更改都将在此更新日志中公布。
如果您对这些指标有反馈,可以在 web-vitals-feedback Google 论坛 中提供。