Find the LCP element in DevTools or with a PerformanceObserver, then split its time into four parts: time to first byte, resource load delay, resource load duration and element render delay. The largest part tells you what to fix: server, discovery and priority, file size, or render-blocking work.
Key takeaways
- LCP has four parts. Time to first byte, resource load delay, resource load duration and element render delay, as web.dev describes them.
- The biggest part is the target. A large load duration means a heavy file; a large load delay means the browser found it late or deprioritised it.
- Render delay usually means something is blocking paint. In the test below, a slow stylesheet added about 1.2 seconds even though the image arrived on time.
- Good is 2.5 seconds or less at the 75th percentile. That is a field target, so test on a throttled profile, not your fast laptop.
- Most pages have one dominant part. In all four cases measured here, a single part made up most of the total.
Finding the element
In Chrome DevTools, Performance panel, record a page load and look for the LCP marker; hovering it names the
element. Or paste this into the console and reload with it registered early (a snippet in Sources, or
PerformanceObserver with buffered: true):
new PerformanceObserver(list => {
const e = list.getEntries().pop();
console.log(e.element, e.url, Math.round(e.renderTime || e.loadTime) + 'ms');
}).observe({ type: 'largest-contentful-paint', buffered: true });
Splitting the time
For an image element, the four parts come from the navigation and resource timing entries:
- Time to first byte: navigation
responseStart. - Load delay: image
requestStartminus TTFB, the time before the browser even asks for the image. - Load duration: image
responseEndminusrequestStart. - Render delay: LCP time minus image
responseEnd.
Four measured cases
Chromium 141, mobile viewport, throttled to 150 ms latency and about 1.6 Mbps, median of three runs per case, on a local server I control.
| Case | LCP | TTFB | Load delay | Load duration | Render delay |
|---|---|---|---|---|---|
| Large image, nothing else slow | 2,932 | 3 | 166 | 2,733 | 13 |
| Slow server (1,000 ms to first byte) | 1,328 | 1,003 | 11 | 300 | 14 |
| Lazy image behind a 1,000 ms stylesheet | 1,492 | 3 | 1,175 | 300 | 14 |
| Eager image, stylesheet takes 1,500 ms | 1,688 | 2 | 166 | 300 | 1,221 |
Each case has a different winner, and the fix changes with it. The third row is the lazy-loading problem in lazy-loading your hero image: the image was not requested until layout was known, so load delay dominated.
Which part, which fix
| Dominant part | What it means | Fix | Basis |
|---|---|---|---|
| Time to first byte | Server or network is slow before any content | Caching, a closer server, less server work; see slow hosting | Measured |
| Load delay | The browser found or prioritised the image late | Remove loading="lazy" from it; put it in the HTML; consider fetchpriority="high" | Measured and documented |
| Load duration | The file is too heavy for the connection | Resize to the displayed size; use a modern format; compress | Measured |
| Render delay | Something blocks painting after the image arrives | Inline critical CSS or shrink render-blocking CSS and scripts | Measured |
web.dev gives a rough guide for a healthy split, with most of the time in first byte and download and little in the two delays. Treat it as a guide, not a threshold: what matters is that no delay is larger than it needs to be. The two delay parts are the cheapest to fix, because they are about ordering, not bytes. To see how this connects to the report in Search Console, read PageSpeed green, Search Console red.