Largest Contentful Paint (LCP) measures how long it takes for the single largest piece of content visible in the viewport to finish rendering: usually a hero image, a background image, or a big block of text. It is Google’s proxy for the question “when does the page feel loaded to the visitor?”, and one of the three Core Web Vitals that influence search ranking.
What the browser picks as the LCP element
The browser watches the viewport as the page loads and repeatedly picks the largest element
painted so far. Candidates include <img>, a background-image on a block element,
<video> poster frames, and large text blocks. The element can change several times during
load, and the final one, largest at the moment loading settles, is your LCP element.
Where the 2.5-second line comes from
The Good / Needs-work / Poor bands sit in the summary panel. Google grades LCP at the 75th percentile of real visits (field data), so a page passes only when three in four visits load that fast. Lab tools like Lighthouse report a single simulated figure instead, which is why your lab and field numbers rarely agree.
What pushes the largest paint late
These are the causes we record most often in our own audit logs, roughly in order of how frequently they turn up:
- The main image is never prioritised. In our snapshot of audited sites (2026-07-23) this was true of 48 of 49 Duda sites, 43 of 57 WordPress sites and 24 of 30 Wix sites: the hero downloads at the same low priority as a footer icon.
- The hero is hidden from the preload scanner by being a CSS
background-image, by carryingloading="lazy", or by arriving only after JavaScript runs. The browser discovers it late, so it fetches it late. - Render-blocking CSS or JavaScript in the
<head>. Nothing paints, LCP included, until those files are fetched and parsed. - Oversized or heavy-format images. A 3000px JPEG where a display-size WebP would do: more bytes, later paint.
- A slow server. High TTFB pushes the whole timeline back before rendering starts.
- Client-side rendering of the first screen. If a framework paints the hero, LCP waits on JavaScript to download, parse and execute.
What the fixes cost elsewhere
- Preloading the hero at high priority competes with FCP. Mark too many assets
fetchpriority="high"and the browser splits bandwidth between them, so text and critical CSS (your FCP) can arrive later rather than sooner. - Inlining critical CSS bloats the HTML. It removes a render-blocking request, but a large inline block grows the document the server sends first, nudging TTFB and total transfer up.
- Eagerly loading a large hero adds bytes to the critical path, which on a slow connection can hurt LCP itself.
Our own answer to those tensions is arithmetic rather than judgement: we cap how many high-priority preloads go into a page, hold inlined critical CSS to a byte budget, and skip the hero preload entirely when a JavaScript slider owns the first screen.
Making the hero discoverable, in code
The fix is to let the browser find the hero early and fetch it first. A lazy-loaded hero is found late, so preload it at high priority instead:
- <img src="/hero.jpg" loading="lazy">
+ <link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
+ <img src="/hero.webp" fetchpriority="high" alt="…">
When the hero comes from a CSS background-image the preload scanner cannot see it at all.
Send the hint out of band, in an HTTP header. In PHP:
header('Link: </hero.webp>; rel=preload; as=image');
What we do to the hero
WebSpeed preloads the real LCP image with fetchpriority="high", inlines critical CSS so
the first paint is not blocked, defers non-critical JavaScript, and converts images to WebP
on the fly: the levers that move LCP without touching the source site.