Largest Contentful Paint is the Core Web Vital that most often fails, and the one teams most often attack blindly. The usual approach is to compress every image on the site, wait a week, and find the number has barely moved.
That happens because LCP is not one thing. It is four sequential phases, and compressing images only helps if the phase that is actually slow happens to be the one about downloading the image.
What LCP measures
LCP records the moment the largest visible element in the viewport finishes rendering. Usually that is a hero image, a video poster frame, or a large block of heading text.
| Rating | LCP |
|---|---|
| Good | ≤ 2.5 seconds |
| Needs improvement | 2.5 – 4.0 seconds |
| Poor | > 4.0 seconds |
The threshold applies at the 75th percentile of real page loads — meaning three quarters of your visitors need to be under 2.5 seconds, not your median visitor and definitely not your laptop on office wifi.
The four parts
This breakdown is the whole trick. Measure the parts, find the biggest one, fix that.
| Phase | What it is | Healthy share |
|---|---|---|
| Time to first byte | Server responds to the document request | ~40% |
| Resource load delay | Gap between TTFB and the browser starting the LCP fetch | < 10% |
| Resource load duration | Downloading the LCP resource itself | ~40% |
| Element render delay | Gap between download finishing and pixels appearing | < 10% |
Those two small phases are where the surprises live. If either is large, you have a discovery or blocking problem, and no amount of image optimisation will touch it.
Phase 1: time to first byte
If TTFB is already 1.5 seconds, you have one second left for everything else and you will not make it. Nothing downstream can rescue a slow origin.
- Serve pre-rendered HTML where you can. Static generation removes per-request work entirely.
- Cache at the edge. A cached response from a nearby node beats a fast origin a long way away.
- Find slow queries. A single unindexed query in the page path will dominate everything else.
- Check redirects. Every hop before the real document adds a full round trip.
http://→https://→https://wwwis two wasted round trips on every cold visit.
Phase 2: resource load delay — the one that catches everyone
The browser has your HTML. Your hero image is right there in it. And it waits.
It waits because it does not know that image matters more than the other fourteen. The preload scanner finds resources in document order and fetches them at default priority, so your hero competes with a footer icon.
Never lazy-load the LCP element
<img src="/hero.jpg" loading="lazy"> ← this is costing youThis is the most common single cause of a bad LCP score we see. Somebody adds loading="lazy" to every image on the site as a blanket optimisation. For images below the fold it is exactly right. On the hero it explicitly tells the browser to deprioritise the one element the metric is measuring.
Mark it as important instead
<img src="/hero.jpg" fetchpriority="high" decoding="async" width="1600" height="900">fetchpriority="high" tells the browser to fetch this ahead of the queue. It is one attribute, it is widely supported, and on image-led pages it frequently moves LCP more than every other change combined.
If your LCP image is set in CSS as a background rather than in an <img> tag, the preload scanner cannot see it at all — it only appears after the stylesheet has been parsed. Either move it into real markup, or <link rel="preload"> it in the head.
Phase 3: resource load duration
This is the phase everybody optimises first. It does matter — just usually less than the two phases either side of it.
- Serve modern formats. AVIF, then WebP, then a JPEG fallback.
- Serve the right size. A 4000px-wide image displayed at 800px wastes most of what you sent. Use
srcsetandsizes. - Always set `width` and `height`. This costs nothing and prevents layout shift, which is a different Core Web Vital you also have to pass.
- Use a CDN so the bytes start closer to the user.
Phase 4: element render delay
The resource arrived and the pixels still are not on screen. Something is blocking the render.
- Render-blocking CSS. Every stylesheet in the head blocks the first paint. Inline what is needed above the fold, defer the rest.
- Synchronous scripts in the head. Add
defer, or move them. - Fonts. With the default
font-display: block, text is invisible while the font loads — and if your LCP element is text, the metric is waiting on your font file.font-display: swaprenders immediately in a fallback and swaps when ready. - Client-side-only rendering. If the LCP element only exists after hydration, LCP waits for your JavaScript bundle to download, parse and execute.
That last one is why a heavy single-page application can post a poor LCP while every individual asset looks fine in isolation.
Measure the field, not your laptop
Lab tools give you a clean, reproducible number on simulated hardware. That number is useful for debugging and is not what Google uses.
Ranking signals come from field data — the Chrome User Experience Report, gathered from real visitors on real devices and real networks. A site that scores well in a lab test and poorly in the field almost always has a mid-range Android and mobile-network problem that a desktop test cannot reveal.
Check both. Use lab tools to find the cause, and field data to confirm the fix reached actual users.
The order to work in
- 1Break your LCP into the four phases before changing anything.
- 2If TTFB is over about 800ms, fix that first — nothing else will matter.
- 3Check the LCP element is not lazy-loaded, and add
fetchpriority="high". - 4If it is a CSS background image, preload it or move it into markup.
- 5Then optimise format and dimensions.
- 6Then remove render-blocking CSS, scripts and font behaviour.
- 7Re-measure in the field, not the lab.
Steps three and four are frequently the whole job. It is deflating to spend a sprint on an image pipeline and then discover a single loading="lazy" was the problem — so check that first.
Web Development
Secure, scalable, high-performance websites and web apps tailored to your business — e-commerce, CMS, and custom builds. Free consultation with NEXHUB Technology.
See how we run it →