Largest Contentful Paint is the Core Web Vitals metric that measures when the biggest visible element in the viewport finishes rendering. Google targets under 2.5 seconds as Good, and anything over 4.0 seconds is Poor. It sounds simple, but the path from a Poor score to a Good one involves multiple layers of the stack — server, network, HTML, and images — and fixing one layer without addressing the others often produces disappointing results.
What the Browser Actually Measures
The browser identifies the largest element by area that is visible in the viewport at the time it paints. That is usually a hero image, a full-width banner, or occasionally a large block of text. If the element changes — say, a late-loading image replaces a placeholder — the LCP candidate updates until the user first interacts with the page. The final reported LCP is the timestamp of the last candidate that was the largest at the time it painted.
You can confirm your LCP element in Chrome DevTools: open the Performance panel, record a page load, and look for the LCP marker in the Timings row. The element is highlighted in the viewport at that timestamp. This identification step matters — I have seen teams spend hours optimizing a hero image only to find out the actual LCP element was a large above-the-fold paragraph with a slow-loading web font.
The Four Phases That Add Up to LCP
Google breaks LCP into four sub-parts: Time to First Byte (TTFB), resource load delay, resource load time, and render delay. Each one is a separate problem with a separate fix:
- TTFB — slow hosting, no CDN, or a slow origin server. Fixes are at the infrastructure layer: faster hosting, server-side caching, CDN with edge nodes close to your users.
- Resource load delay — the LCP image is not discovered early in the HTML. The browser finds it late because it is set via a CSS background-image or injected by JavaScript. Fix: use an
<img>tag in the HTML, or add a preload hint so the browser fetches it at high priority before parsing the image tag. - Resource load time — the image file itself is too large or served uncompressed. Fix: serve WebP or AVIF, compress to 75–85% quality, and size the image to the actual display dimensions rather than a larger original.
- Render delay — render-blocking scripts or stylesheets above the fold delay when the browser can paint. Fix: defer non-critical JavaScript, inline critical CSS so the browser can start painting without waiting for a separate stylesheet request.
The Preload Fix — and When It Backfires
Adding <link rel='preload' as='image' href='/hero.webp'> to the <head> tells the browser to fetch the LCP image at the highest priority, before the HTML parser even reaches it. This is often the single biggest win for hero images. The caveat: if the image is responsive — different files for different viewports — you need the imagesrcset and imagesizes attributes on the preload link, or you risk preloading the wrong file for the visitor’s device. Preloading a desktop-sized image on mobile wastes bandwidth and may not even be the LCP element on that viewport.
Lazy Loading and the LCP Trap
WordPress 5.5 and later automatically adds loading='lazy' to images. That is great for below-the-fold images — it reduces initial page payload. But if the LCP image gets that attribute, the browser intentionally delays fetching it, which tanks the LCP score. The fix is explicit: set loading='eager' on the hero image, or use the wp_lazy_loading_enabled filter to exempt the first image in the content area. I have seen this single change move LCP from Poor to Good on sites that were otherwise well-optimized — it is one of the first things I check in a technical SEO audit.
Image Format and Compression
Serving a 400KB JPEG hero when a 90KB WebP delivers identical visual quality is a direct, avoidable hit on LCP. Convert hero images to WebP — it delivers 25–35% smaller files than JPEG at equivalent quality and is supported by all modern browsers. AVIF goes further (40–50% smaller than JPEG) but has slightly narrower browser support — worth using on high-traffic landing pages where the savings are significant. Size images to the actual rendered dimensions. Serving a 2400px image in a 1200px-wide container means the browser downloads twice the data it needs. Use srcset to serve device-appropriate sizes and the browser will pick the right one automatically.
Text as the LCP Element
On text-heavy pages — blog posts, pillar pages — the LCP element is often the first large paragraph or heading. Web fonts are the main culprit here. If the font is loading from Google Fonts or Adobe Fonts with no preconnect and no font-display: swap, the browser blocks rendering until the font arrives. Self-hosting fonts and adding font-display: swap to the @font-face declarations eliminates most of the delay. Add a <link rel='preconnect'> tag for any font CDN you use so the DNS resolution and TCP connection happen earlier.
CDN and Caching
If your LCP image is served from the same origin as your HTML and that origin is a single server in Virginia serving users in California, you are adding unnecessary round-trip latency to every image fetch. A CDN with edge nodes close to your users reduces resource load time directly. For a Phoenix-area business serving the broader US, most of your audience is spread across time zones — a CDN is not optional if you want consistently Good scores in field data across that geographic spread. Confirm the CDN is actually serving the image, not just the HTML; misconfigured CDNs that cache HTML but not media assets are common. Related: HTTPS and SEO.
Render-Blocking Resources
Any script tag in the <head> without defer or async blocks HTML parsing until that script downloads and executes. If you have three such scripts before the LCP image tag, the image fetch cannot even start until all three scripts are done. Audit your script loading order. Add defer to all scripts that do not need to run before the DOM is ready. Inline truly critical scripts (usually small) rather than loading them as external files.
Measuring Progress in the Field
Do not chase lab scores in isolation. Use the Chrome User Experience Report data in Google Search Console or via the CrUX API to track real-user LCP by URL group. A lab score of 1.8s means nothing if 25% of your real users are on slower connections and seeing 5s in the field. Related: HTTP status codes for SEO. The field data is what Google uses for ranking signals, and it is segmented by device — make sure you are looking at both mobile and desktop field data, not just whichever one looks better.
LCP is one dimension of a broader technical picture. A full website audit puts LCP data in context alongside crawl health, indexation, and structured data. For the remediation side — how to sequence fixes across all three Core Web Vitals — see Core Web Vitals optimization. If page speed is the broader concern, page speed optimization covers the server and delivery stack in more depth.