What is Largest Contentful Paint (LCP)?
Largest Contentful Paint — LCP — is the time it takes for the biggest visible element on a page to finish rendering. "Biggest" is measured in pixel area inside the initial viewport. For most pages that's the hero image, the main product photo, or a large headline block.
LCP is one of the three Core Web Vitals Google uses to judge page experience. It replaces First Meaningful Paint (retired in 2020) because "meaningful" was too subjective — LCP, by contrast, is a purely mechanical measurement a browser can compute without guessing intent.
Thresholds
Google groups LCP into three buckets based on the p75 of real Chrome users:
- Good: 2.5 seconds or less
- Needs improvement: 2.5 to 4.0 seconds
- Poor: over 4.0 seconds
The p75 matters. It means 75% of your users experienced this time or better. If your p75 is 3.8 seconds, 25% of users are waiting longer than 3.8 seconds for the main content — which almost always includes users on slower devices, slower networks, or both.
What element gets counted
Chrome picks the largest element inside the viewport, ignoring elements with zero opacity, elements outside the viewport, and tiny-by-definition elements like bullets. The candidate is usually:
- A large
<img> - A
<video>poster - An element with a CSS
background-image - A text node inside a large block (paragraph, heading)
Chrome continues tracking candidates until the user interacts or the page finishes loading — whichever comes first. The final LCP is the last candidate before user interaction.
How to measure
There are two paths:
- Lab — PageSpeed Insights, Lighthouse, WebPageTest. Simulates a load and measures. Fast, consistent, good for debugging but doesn't reflect real users.
- Field — Chrome's CrUX dataset, the
web-vitalsnpm library running on your own site, or tools that surface CrUX (like this one). Reflects real users.
Field data is what Google uses for rankings. Lab data is what you use to test fixes.
Common causes of slow LCP
Almost every slow LCP traces to one of these:
- Unoptimized hero image — 2MB JPEG where a 150KB AVIF would do
- Slow server response (high TTFB) — page can't even start rendering
- Render-blocking JavaScript — large bundles the browser parses before first paint
- Render-blocking CSS — stylesheets that don't ship critical CSS inline
- Client-side rendering for above-the-fold content — React mounts, fetches, renders, then LCP fires
- Fonts that swap mid-render — text LCP is delayed waiting for the font
Fixes that actually move the number
- Serve hero images in AVIF/WebP with explicit
widthandheight - Add
fetchpriority="high"and<link rel="preload">for the LCP image - Put the site behind a real CDN (Cloudflare, Vercel, Fastly)
- Ship critical CSS inline, defer the rest
- Move heavy JavaScript off the critical path —
asyncordeferscripts, or split with dynamic imports - Server-render (or static-render) above-the-fold content instead of client-rendering it
- Use
font-display: swaporoptionalto prevent font-blocking
A quick diagnostic
Run PageSpeed Insights, check which element got flagged as the LCP candidate, and ask: is that element loaded from an image, a font, or JavaScript? The answer usually points to the fix within two minutes.