Web Speed

The Real Reason Your Largest Contentful Paint Won’t Drop Below 2.5s

You compressed the images, installed the caching plugin, minified everything — and LCP still reads 3.4 seconds. Stuck-LCP sites almost always share the same diagnosis: the optimizations treated the image, but LCP is a relay race, and the handoffs are where the time hides.

LCP isn’t one delay — it’s four in a row. Optimizing the last leg while the first three crawl is why your score won’t move.

The four legs of the race

Before your hero image can paint, four things happen in sequence: the server responds (TTFB), the browser discovers the image exists, the image downloads, and the browser renders it. Google’s LCP optimization guide breaks the metric down exactly this way — and the discovery and TTFB legs, not the download, are where stuck sites lose their seconds.

Leg 1: TTFB — the floor under everything

If your server takes 1.2 seconds to send the first byte, a 2.5-second LCP needs everything else to finish in 1.3 — nearly impossible. Check TTFB first; if it’s over ~600ms, fix server-level page caching before touching another image. No amount of compression outruns a slow first byte.

Leg 2: Discovery — the invisible delay

This is the one nobody checks. The browser can only start downloading the hero once it knows about it, and modern setups hide the hero from the initial HTML in several ways: the image set as a CSS background-image (invisible until the CSS downloads and parses), injected by JavaScript or a slider (invisible until scripts run), or — the self-inflicted classic — marked loading="lazy", which explicitly tells the browser to wait on the exact image being timed. Each pattern adds hundreds of milliseconds of pure discovery delay before a single byte of image transfers.

The fix pattern

Get the hero into the initial HTML as a real <img> tag, remove lazy loading from it, add fetchpriority="high", and preload it in the head. Together these move the image download to the front of the queue instead of the back — routinely worth a full second on sites that had it backwards.

Leg 3: Render-blocking resources in the way

Even a discovered, downloaded image can’t paint until render-blocking CSS and JavaScript finish. Builder themes shipping 1–2MB of CSS and font stacks loading four families make the browser sit on a ready image. Cut unused CSS, defer non-critical scripts, and trim to two font families with preloaded primaries — this leg is where “the score improved but only a little” sites find their remaining half-second.

Leg 4: The image itself — the leg you already fixed

Modern format, sized to its container, decently compressed. Necessary, already done, and only ever one leg of four — which is precisely why doing it alone didn’t move the number.

Diagnose in this order

PageSpeed Insights names your LCP element — confirm it’s the hero and not a surprise (a font-rendered headline or an unexpected banner changes the whole plan). Then read the phases: high TTFB → server caching; long “resource load delay” → discovery fixes; long render delay → blocking CSS/JS. Fix the biggest phase, re-measure, repeat. When the phases point at theme architecture itself — CSS bloat, JS-rendered heroes — that’s the point where a structured speed pass beats another plugin, because the problem is in the build, and so is the fix.

keep reading

Related articles

Tell me what you want to build

A website, an app, some automation — or something you’re still figuring out. Tell me the problem and I’ll give you a straight answer on what it takes. No pressure, no sales team.

You’ll deal with me directly — usually a reply within a day.