largest contentful paint:先量再拆,修占比最大的那一段
largest contentful paint 是视口里最大那块内容渲染完成的时间,目标是 2.5 秒以内。这篇讲怎么找到那个元素、把它拆成四个子部分、并只修占比最大的那一段。

largest contentful paint 说的是视口里最大那块内容渲染完成的时间,目标是 2.5 秒以内。Google 的定义很死:LCP「reports the render time of the largest image, text block, or video visible in the viewport, relative to when the user first navigated to the page」(见 web.dev,2026-09-30 访问)。它没达标,不是你丢了一个排名因子,是你丢了陌生访客落地后的头两秒。
读这篇之前
你只需要一个能在浏览器里打开的页面,和一台能跑命令行的机器,没有别的门槛。有三篇挨着它:想先确认「速度到底值不值得投入」,看 core web vitals 值不值得做,这一篇默认你已经答完那个问题;想把数字用脚本而不是手点取出来,看 PageSpeed Insights API 怎么用;想看这批阻塞资源在真实站点上出现得多不多,看 26 个首页的阻塞渲染 CSS。
largest contentful paint 量的是什么,哪块才算「最大的元素」
它是一个定义很窄的单个数字。浏览器盯着视口,记下已经绘制过的最大的那个元素,报告从导航开始到它渲染完成的时间。这块元素会变:一开始可能是标题最大,等首图加载完,首图顶上来。指标报的是最后那个候选,因为访客实际等的是它。
够格的元素只有几类,这份清单是故意收窄的,不是随手定的:
<img>元素,动图取第一帧。<svg>里的<image>。<video>,取它的 poster 图或第一帧,哪个先到算哪个。- 用
url()设了背景图的元素,纯 CSS 渐变不算。 - 内容是文字的块级元素。
Chromium 还会跳过访客不会当成内容的那几类:完全透明的元素、铺满整个视口更像背景的元素、低熵的占位图。比大小用的是视口里可见的尺寸,裁剪后算;图片被缩放过时,取渲染尺寸和原始尺寸里更小的那个。
largest contentful paint 不是「页面加载完」的时间,是「屏幕上最要紧的那一块终于出现」的时间。
一个数字底下压着四个不同的问题
单独一个 LCP 值只能告诉你页面慢,从来不告诉你慢在哪。有用的做法是把它拆成四个子部分,四段之和等于全长,彼此不重叠。每个页面都能这么拆,每一段指向一种不同的修法。
| 子部分 | 覆盖什么 | 健康占比 |
|---|---|---|
| 首字节时间 | 从导航开始到收到 HTML 第一个字节 | 约 40% |
| 资源加载延迟 | 首字节到 LCP 资源开始加载 | 低于 10% |
| 资源加载耗时 | LCP 资源本身传输花了多久 | 约 40% |
| 元素渲染延迟 | 资源到位到元素真正渲染出来 | 低于 10% |
这几个比例是参考值不是硬指标,web.dev 原文写得很清楚:它们只有相互比较才有意义,所以别把它换算成绝对毫秒。要紧的是形状 —— 大部分时间应该花在搬 HTML 和 LCP 资源上,任何两件都没在搬的窗口,就是可以省的地方。
这套比例还解释了一个坑。把图片压小,可能只是缩短了「资源加载耗时」这一段,而总时间一点没动,因为省下来的时间转进了「元素渲染延迟」。把首图藏在脚本后面再显示的页面就是这样:字节到得更早,图还是在原来那一秒出现。
按这个顺序做
四步,每一步都有个可以核对的完成标志,过了再走下一步。
- 先看 field 数,再看 lab 数。指标服务的是真实访客,而一台快电脑上的 lab 跑分不代表他们。完成标志:你能分手机和桌面,各说出 75 分位的 LCP。
- 找出 LCP 元素。你得先知道那块大的到底是图、是标题还是视频,才知道怎么修。完成标志:你能贴出这个元素的选择器和它的类型。
- 把这个值拆成四段。完成标志:你能说清哪一段最大,并指出是哪条资源造成的。
- 只修占比最大的那一段。改一处,重测一次。完成标志:那一段降了,总数跟着降。
交付物:一段代码、一条命令、一张判读表
这段代码贴进页面或直接在控制台跑,会打印出每一个 LCP 候选元素和它背后的元素。它用的就是 field 工具用的那个观察器,只是少了统计那层。
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('LCP candidate:', entry.startTime, entry.element);
}
}).observe({type: 'largest-contentful-paint', buffered: true});
它最后打印的那一行通常就是你的 LCP,但不总是,API 自己说明了差别:对在后台标签页打开的页面它照样报候选,而指标不看这些;对从前进后退缓存恢复的页面它什么都不报,而指标是算的。web-vitals 库替你处理了这些边界,给出的就是 Chrome User Experience Report 用的那个数。
命令行这边,一条命令一次拿到 lab 数和 LCP 元素:
npx lighthouse https://example.com \
--only-audits=largest-contentful-paint,largest-contentful-paint-element \
--output=json --output-path=lcp.json --quiet
读它的时候把 field 数摆在旁边,而不是拿它替代。两者对不上时,信 field 那一侧。
定了哪一段最大之后,修法通常就下面五种之一:
| 子部分 | 常见成因 | 怎么修 |
|---|---|---|
| 加载延迟 | 首图由脚本插入,或用了懒加载库 | 把 src 写进 HTML,LCP 图绝不懒加载 |
| 加载延迟 | 浏览器不知道这张图要紧 | 加 fetchpriority="high",或预加载它 |
| 渲染延迟 | head 里有大样式表或同步脚本 | 内联或压缩 CSS,脚本 defer 掉 |
| 加载耗时 | 文件过大、格式过时、离用户太远 | 缩尺寸、换新格式、从更近的边缘节点发 |
| 首字节时间 | 跳转链、源站没缓存、服务器太远 | 砍掉跳转、缓存 HTML、把源站挪近 |
其中两条单独值得记住。绝不给 LCP 图加懒加载:懒加载要等布局确认图片进了视口才去请求,而这段等待正是你要消掉的那个延迟。高优先级只给一张图,别给五张,优先级一散开就等于没设。
我们测到的,以及它证明不了什么
2026-09-30 我们用 Lighthouse 12 每站跑了一次,mobile,单次。出来两个数字,都打了写这篇的人的脸。Google 自己那份教你怎么做这个指标的 LCP 指南,跑出来 3.2 秒。我们自己的首页 querywin.com,跑出来 5.8 秒。两个都在 2.5 秒目标之上,我们那个还在文档所写的 4.0 秒「poor」线之上。
这一次运行就是全部样本,所以把它当快照,不是基准。lab 跑分是用固定设备和限速网络做的模拟,和访客的真实体验对不上:它没法告诉你真实数是更好还是更差,而就我们自己这个站,我们也还没把两边比过。它显示的是一条底线 —— 连讲 largest contentful paint 的页面都过不了自己这一关,一个从没看过这个数的页面,多半也没过关。
三种常见的错法
前两种浪费一个迭代。第三种是很多人最后放弃这个指标的原因。
- 优化错了元素。团队把标签里第一张图压了半天,而它经常不是 LCP 元素。先量准那个元素,再动文件。
- 只在 lab 里量。笔记本上快网络下的一百分,不等于 field 数好看,而指标报的是 field 数。
- 修完一段就收手。只把时间从一段挪到另一段的改动,总数不会变。每改一次都重测,否则你分不出自己做的是哪种。
常见问题
largest contentful paint 是排名因素吗
它属于 Core Web Vitals,而 Google 把它列在众多输入之一,我们不会把它说成更多。要修它,站得住的理由是一个 2.5 秒内把主内容画出来的页面,能留住更多落进来的人。
多少算好
2.5 秒以内,按访问量的 75 分位算,手机和桌面分开各自看。超过 4.0 秒算差,中间那段算需要改进。
图片要不要懒加载来改善 LCP
首屏以下的图可以懒加载,LCP 那张不行。给最大的首屏元素加懒加载,加进去的正好是这个指标量的那段延迟。
为什么不同工具测出来不一样
因为 lab 工具和 field 数回答的是两个问题。lab 工具跑一次模拟加载,field 数汇总真实访问。两者打架时,field 数描述的是你的访客,lab 数只帮你解释它。
下一步
largest contentful paint 告诉你页面什么时候变得可用。页面体验的另一半,是它加载的时候版式有没有乱跳,那是单独的一章。这一篇只让你带走一个循环:量出元素,拆成四段,修最大的那段,再量一次。在访客真正落地的那几个页面上把这个循环跑完,正是 QueryWin 在做的事。
本文属于 QueryWin 实操手册 · 第 2 阶


