Largest Contentful Paint is the Core Web Vital that most often fails, and the one most teams fix wrong. A practical diagnosis sequence: find the LCP element, find the delay, fix the right layer.
Of the three Core Web Vitals, Largest Contentful Paint is the one we see failing most often in audits, and also the one teams most often fix incorrectly. The usual story: the score is red, someone Googles “improve LCP,” installs a caching plugin, compresses some images, and the score stays red. Then everyone concludes performance work doesn’t help.
The problem isn’t the effort. It’s that LCP failures have four distinct causes, and each needs a different fix. Compressing images when your real problem is server response time is like tuning a guitar that isn’t plugged in. Here’s the diagnosis sequence we actually use.
First, Understand What LCP Measures
LCP is the time until the largest visible element on the initial screen finishes rendering. Usually that’s your hero image, a banner, or a big headline block. Google’s threshold: under 2.5 seconds is good, over 4 seconds is failing. Full definitions live at web.dev/vitals, but that one sentence is 90 percent of what you need.
The key insight: you’re not speeding up “the page.” You’re speeding up one specific element. So the first job is finding out which one.
Step 1: Identify Your LCP Element
Run your page through PageSpeed Insights and scroll to the diagnostics: it names the LCP element outright. Nine times out of ten it’s the hero image. Occasionally it’s a text block waiting on a slow web font, or a background image nobody remembered was 2MB.
Also check whether field data (real users) and lab data disagree. Lab tests simulate one device; field data is what actual visitors experienced over 28 days. Field data is the truth. Lab data is the debugger.
Step 2: Find Where the Time Actually Goes
An LCP delay lives in one of four phases, and PageSpeed’s waterfall tells you which:
Server delay (TTFB). If the server takes 1.5 seconds to send the first byte, no image optimisation can save you. Causes: cheap hosting, no caching layer, bloated server-side rendering. Fix at the hosting/caching layer.
Render blocking. The browser has the HTML but sits idle, chewing through CSS files and scripts before it will paint anything. Fix: cut unused CSS, defer non-critical scripts, inline the small amount of CSS the first screen truly needs.
Resource delay. The browser didn’t even start downloading your hero image until late, usually because the image is loaded via CSS, injected by JavaScript, or (a classic we keep finding) someone set loading="lazy" on the hero. Never lazy-load your LCP element; it’s the one thing the page exists to show. Fix: a plain <img> tag in the HTML, plus a fetchpriority="high" hint or a preload.
Resource duration. The download started promptly but the file is simply huge. This is the only case where “compress your images” is the right answer. Serve modern formats (WebP or AVIF), size the image to its actual display dimensions, and let a CDN do the delivery.
Step 3: Fix in Order, Measure Between
Work top of the waterfall downward: server first, blocking second, delay third, size last. Each fix changes the shape of the problem, so re-test after every change rather than shipping five fixes blind. We’ve seen a single change (removing lazy-loading from a hero image) take LCP from 4.8s to 2.1s, and we’ve seen teams spend a week on image compression that moved the needle 200ms because the real problem was a 1.9-second server response.
The Boring Preventive Truth
Every failing LCP we’ve fixed was cheaper to prevent than to cure: choose a lean stack, treat the hero image as sacred, and test on a real phone over mobile data before launch, not after the ad spend starts. Speed problems are design decisions wearing a technical costume, which is exactly why they’re revenue problems.
Red scores you can’t explain? We diagnose and fix this for a living, and we’ll tell you which of the four phases is eating your seconds before we propose anything.