What LCP measures
The moment the largest element in the viewport finished rendering — usually a hero image, a video poster, or a block of heading text. It is a proxy for "the page looks ready", and it is the vital that most often fails.
It is measured in the viewport, so the element that counts is whatever dominates the first screen; and it keeps updating until the user first interacts, which is why a late-loading banner can make it worse than it felt.
The four parts it breaks into
Google's own field data says load delay and render delay are together the majority of LCP on most sites — not the download itself. The bytes are the obvious suspect and rarely the biggest one.
| Part | Usually | Fix |
|---|---|---|
| Time to first byte | server, redirects, no caching | the server lesson, and a CDN |
| Resource load delay | the browser did not know about it yet | put it in the HTML; preload; no lazy-loading the hero |
| Resource load time | the file is too big | the images lesson |
| Render delay | blocked by CSS, fonts or JavaScript | the critical-path lesson in the web course |
The single most common bug
Lazy-load everything below the fold and nothing above it. A lazily-loaded hero is discovered late, downloaded late, and painted late — and it is in a surprising number of production pages because a component applied loading="lazy" to every image it renders.
<img src="/hero.jpg" loading="lazy"> <!-- the LCP element, deferred. Never. -->
<img src="/hero.jpg" fetchpriority="high"> <!-- this is the opposite, and correct -->
Discovery beats bandwidth
The preload scanner reads the raw HTML before the parser is finished and starts fetching what it finds. Anything it cannot see — a CSS background, an image injected by a component, a font referenced inside a stylesheet — waits for whatever comes first.
<!-- discovered by the preload scanner, immediately -->
<img src="/hero.jpg" fetchpriority="high" width="1200" height="600" alt="…">
<!-- discovered after CSS is parsed — hundreds of milliseconds later -->
<div style="background-image: url(/hero.jpg)"></div>
<!-- discovered after JavaScript has downloaded, parsed and run — later still -->
<script>renderHero();</script>
The order to try things
- Find the element. The browser reports it:
entry.elementin the LCP observer, or the Lighthouse trace. Half the time it is not what you assumed. - Is it discoverable in the HTML? If not, make it so, or
preloadit. - Is anything blocking the paint? A render-blocking stylesheet or a synchronous script in the head.
- Is it too big? Then the images lesson.
- Is the server slow? Then the server lesson — and check for a redirect chain first, because each one is a whole round trip.