最大内容绘制 (LCP) 是一个重要的、以用户为中心的衡量感知加载速度的指标,因为它在页面的主要内容可能已加载时标记了页面加载时间线中的点——快速的 LCP 有助于让用户确信页面是有用的.
从历史上看,对于 Web 开发人员来说,衡量网页主要内容的加载速度和对用户可见的速度一直是一个挑战。
像load或DOMContentLoaded这样的旧指标并不好,因为它们不一定对应于用户在屏幕上看到的内容。更新的、以用户为中心的性能指标,如First Contentful Paint (FCP)只捕捉加载体验的开始。如果页面显示启动画面或显示加载指示器,则这一时刻与用户无关。
过去,我们推荐了性能指标,例如首次有意义的绘制 (FMP)和速度指数 (SI)(两者都在 Lighthouse 中可用)来帮助捕获初始绘制后的更多加载体验,但这些指标很复杂,难以解释,而且通常是错误的——这意味着他们仍然无法识别页面的主要内容何时加载。
有时候越简单越好。根据W3C Web 性能工作组的讨论和 Google 的研究,我们发现衡量页面主要内容何时加载的更准确方法是查看最大元素何时呈现。
什么是LCP?#
最大内容绘制 (LCP) 指标报告视口内可见的最大图像或文本块的渲染时间,相对于页面首次开始加载的时间。
什么是好的 LCP 分数?#
为了提供良好的用户体验,网站应努力将最大内容绘制时间设为2.5 秒或更短。为确保您的大多数用户都能达到此目标,一个很好的衡量阈值是页面加载的第 75 个百分位数,在移动设备和桌面设备之间进行细分。
要了解有关此建议背后的研究和方法的更多信息,请参阅:定义 Core Web Vitals 指标阈值
考虑哪些要素?#
目前在Largest Contentful Paint API 中指定,Largest Contentful Paint考虑的元素类型是:
请注意,将元素限制在这个有限的集合中是有意的,以便在开始时保持简单。随着更多研究的进行,未来可能会添加其他元素(例如
元素的大小是如何确定的?#
为最大内容绘制报告的元素大小通常是用户在视口内可见的大小。如果元素延伸到视口之外,或者任何元素被剪裁或具有不可见的溢出,则这些部分不计入元素的大小。
对于从其固有大小调整大小的图像元素,报告的大小是可见大小或固有大小,以较小者为准。例如,缩小到远小于其内在尺寸的图像将仅报告其显示时的尺寸,而拉伸或扩展至更大尺寸的图像将仅报告其内在尺寸。
对于文本元素,仅考虑其文本节点的大小(包含所有文本节点的最小矩形)。
对于所有元素,不考虑通过 CSS 应用的任何边距、填充或边框。
确定哪些文本节点属于哪些元素有时会很棘手,尤其是对于子元素包括行内元素和纯文本节点以及块级元素的元素。关键是每个文本节点都属于(并且仅属于)其最近的块级祖先元素。在规范方面:每个文本节点都属于生成其包含块的元素。
什么时候报告最大的内容?#
网页通常分阶段加载,因此,页面上最大的元素可能会发生变化。
为了处理这种潜在的变化,浏览器在浏览器绘制第一帧后立即调度一个标识最大内容元素PerformanceEntry的类型largest-contentful-paint。但是,在渲染后续帧之后,它会PerformanceEntry在最大的内容元素发生变化时调度另一个。
例如,在带有文本和英雄图像的页面上,浏览器最初可能只呈现文本——此时浏览器将调度一个largest-contentful-paint条目,其element属性可能引用 a
或
。稍后,一旦英雄图像完成加载,largest-contentful-paint将分派第二个条目,其element属性将引用
.
需要注意的是,一个元素只有在呈现并且对用户可见后才能被视为最大的内容元素。尚未加载的图像不被视为“渲染”。在字体块期间也不使用网络字体的文本节点。在这种情况下,较小的元素可能会被报告为最大的内容元素,但一旦较大的元素完成渲染,它将通过另一个PerformanceEntry对象报告。
除了延迟加载图像和字体之外,当新内容可用时,页面可能会向 DOM 添加新元素。如果这些新元素中的任何一个大于之前最大的内容元素,PerformanceEntry也会报告一个新元素。
如果当前是最大内容元素的元素从视口中删除(甚至从 DOM 中删除),除非呈现更大的元素,否则它将保持最大内容元素。
在 Chrome 88 之前,移除的元素不被认为是最大的内容元素,移除当前的候选元素会触发一个新的largest-contentful-paint条目被调度。但是,由于流行的 UI 模式(例如经常删除 DOM 元素的图像轮播),该指标已更新以更准确地反映用户体验。有关更多详细信息,请参阅变更日志。
一旦用户与页面交互(通过点击、滚动或按键),浏览器将停止报告新条目,因为用户交互通常会改变用户可见的内容(滚动时尤其如此)。
出于分析目的,您应该只报告最近发送PerformanceEntry给您的分析服务的数据。
注意:由于用户可以在背景选项卡中打开页面,因此在用户聚焦选项卡之前可能不会发生最大的内容绘制,这可能比他们第一次加载它的时间晚得多。
加载时间与渲染时间#
出于安全原因,对于缺少Timing-Allow-Origin标头的跨源图像,不会公开图像的渲染时间戳。相反,只公开它们的加载时间(因为这已经通过许多其他 Web API 公开了)。
下面的使用示例展示了如何处理渲染时间不可用的元素。但是,在可能的情况下,始终建议设置Timing-Allow-Origin标题,以便您的指标更加准确。
如何处理元素布局和大小更改?#
为了保持计算和分派新性能条目的性能开销较低,对元素大小或位置的更改不会生成新的 LCP 候选。仅考虑元素在视口中的初始大小和位置。
这意味着最初在屏幕外渲染然后在屏幕上过渡的图像可能不会被报告。这也意味着最初在视口中呈现的元素然后被推下,视图外仍将报告它们的初始、视口内大小。
例子#
以下是一些流行网站上发生最大内容绘制时的一些示例:
在上面的两个时间线中,最大的元素随着内容加载而变化。在第一个示例中,新内容被添加到 DOM 并且改变了最大的元素。在第二个示例中,布局更改并且以前最大的内容从视口中删除。
虽然延迟加载的内容通常大于页面上已有的内容,但情况并非一定如此。接下来的两个示例显示了在页面完全加载之前发生的最大内容绘制。
在第一个示例中,Instagram 徽标加载得相对较早,即使其他内容逐渐显示,它仍然是最大的元素。在 Google 搜索结果页示例中,最大的元素是在任何图像或徽标完成加载之前显示的一段文本。由于所有单个图像都小于此段落,因此在整个加载过程中它仍然是最大的元素。
在 Instagram 时间线的第一帧中,您可能会注意到相机徽标周围没有绿框。这是因为它是一个
如何测量 LCP #
现场工具#
- Chrome 用户体验报告
- PageSpeed 洞察力
- Search Console(核心 Web Vitals 报告)
-
实验室工具#
- 灯塔
-
在 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条目记录到控制台,但在 JavaScript 中测量 LCP 更为复杂。详情请见下文:
在上面的例子中,每个记录的largest-contentful-paint条目代表当前的 LCP 候选者。通常,startTime发出的最后一个条目的值是 LCP 值——但是,情况并非总是如此。并非所有largest-contentful-paint条目都适用于测量 LCP。
以下部分列出了 API 报告的内容与指标计算方式之间的差异。指标和 API 之间的差异#
API 将为largest-contentful-paint背景选项卡中加载的页面调度条目,但在计算 LCP 时应忽略这些页面。
- API 将largest-contentful-paint在页面被后台处理后继续分派条目,但在计算 LCP 时应忽略这些条目(仅当页面始终处于前台时才考虑元素)。
- largest-contentful-paint当页面从后退/前进缓存恢复时,API 不会报告条目,但在这些情况下应该测量 LCP,因为用户将它们体验为不同的页面访问。
- API 不考虑 iframe 中的元素,但要正确测量 LCP,您应该考虑它们。子框架可以使用 API 将它们的largest-contentful-paint条目报告给父框架进行聚合。
开发人员可以使用web-vitalsJavaScript 库来衡量 LCP,而不是记住所有这些细微的差异,它会为您处理这些差异(在可能的情况下):
import {getLCP} from ‘web-vitals’;
// Measure and log LCP as soon as it’s available.
getLCP(console.log);
有关如何在 JavaScript 中测量 LCP 的完整示例,您可以参考源代码getLCP()。
在某些情况下(例如跨域 iframe),无法在 JavaScript 中测量 LCP。有关详细信息,请参阅库的限制部分web-vitals。
如果最大的元素不是最重要的怎么办?#
在某些情况下,页面上最重要的元素(或多个元素)与最大的元素不同,开发人员可能更感兴趣的是测量这些其他元素的渲染时间。这可以使用Element Timing API 实现,如关于自定义指标的文章中所述。
如何改进 LCP #
LCP主要受四个因素影响:
- 服务器响应速度慢
- 渲染阻塞 JavaScript 和 CSS
- 资源加载时间
- 客户端渲染
要深入了解如何改进 LCP,请参阅优化 LCP。有关也可以改进 LCP 的单个性能技术的其他指导,请参阅:
- 使用 PRPL 模式应用即时加载
- 优化关键渲染路径
- 优化你的 CSS
- 优化您的图像
- 优化网页字体
优化您的 JavaScript(针对客户端呈现的网站)
其他资源#
Annie Sullivan在performance.now() (2019) 上从 Chrome 中的性能监控中吸取的教训
变更日志#
有时,会在用于衡量指标的 API 中发现错误,有时也会在指标本身的定义中发现错误。因此,有时必须进行更改,这些更改可能会在您的内部报告和仪表板中显示为改进或回归。
为了帮助您管理这一点,对这些指标的实现或定义的所有更改都将在此CHANGELOG 中显示。