How to Improve LCP (Largest Contentful Paint) in WordPress

Improving LCP in WordPress — laptop displaying website speed optimization

How to Improve LCP (Largest Contentful Paint) in WordPress

If your site scores well on desktop but PageSpeed Insights keeps flagging mobile, the culprit is usually Largest Contentful Paint. When you improve LCP in WordPress, you fix the one metric visitors actually feel: the moment the biggest thing on screen finally shows up. LCP is one of Google’s three Core Web Vitals, and it carries 25% of your Lighthouse performance score.

This guide continues my Core Web Vitals series (TTFB covered how fast the server answers, INP covered how fast the page responds to clicks). This time: how fast the page’s largest visible element renders — and the concrete steps to make it faster.

What LCP Actually Measures

LCP measures the render time of the largest content element visible in the viewport during page load. In practice, that’s almost always one of two things: your hero image or your main headline text. Google’s thresholds are straightforward:

  • Good: 2.5 seconds or less
  • Needs improvement: 2.5–4.0 seconds
  • Poor: more than 4.0 seconds

Those thresholds are measured at the 75th percentile of real user visits (field data), which is what Google uses for rankings — not your lab test.

Google breaks every slow LCP into four subparts: time to first byte (covered in my TTFB guide), load delay (how long before the browser even starts fetching the LCP resource), load duration (how long the download takes), and render delay (the gap between download finishing and the element appearing). Each step below attacks one of these.

Step 1: Find Your Actual LCP Element

Don’t optimize blindly. Open Chrome DevTools → Performance panel, record a page load, and find the LCP marker — it tells you exactly which element Google is measuring. Nine times out of ten it’s the hero image on your homepage, or the featured image on blog posts.

In PageSpeed Insights, the “Largest Contentful Paint element” diagnostic shows you the element plus the subpart breakdown, so you can see whether the problem is a slow start (load delay), a slow download (load duration), or a slow render (render delay). Fix the phase that’s actually slow first.

Step 2: Stop Lazy-Loading Your Hero Image

This is the single most common LCP mistake on WordPress sites, and the most expensive one: the LCP image must never be lazy-loaded. Lazy loading tells the browser to wait — the exact opposite of what you want for the largest element on screen.

As covered in my lazy loading guide, WordPress core has handled this correctly since WordPress 6.3: it automatically adds fetchpriority="high" to the image most likely to be the LCP element, and never combines it with loading="lazy". The two attributes are mutually exclusive.

So first, verify your site is actually benefiting from this:

  1. Open your homepage in Chrome and inspect the hero <img> tag.
  2. It should have fetchpriority="high" and no loading="lazy" attribute.
  3. In PageSpeed Insights, check the diagnostics — if you see “Largest Contentful Paint image was lazily loaded,” something is overriding core: a theme that hard-codes <img> tags, a page builder outputting its own markup, or an optimization plugin forcing lazy load on everything.

The fix: exclude the hero from lazy loading in your optimizer’s settings, or if your theme outputs the image manually, add the attribute yourself:

// functions.php — make sure your hero image loads with high priority
add_filter('wp_get_attachment_image_attributes', function ($attr) {
    if (is_front_page() && !isset($attr['fetchpriority'])) {
        $attr['fetchpriority'] = 'high';
        unset($attr['loading']); // never lazy-load the hero
    }
    return $attr;
});

Step 3: Preload the LCP Image

fetchpriority="high" tells the browser to prioritize the image once it finds it. But if the browser only discovers the image late — say it’s rendered by a page builder’s markup deep in the HTML, or it’s a CSS background image — that’s precious time lost. A preload hint in the document <head> tells the browser to start downloading the image before it even finishes parsing the page:

// functions.php — preload the front-page hero image
add_action('wp_head', function () {
    if (is_front_page() && has_post_thumbnail()) {
        $hero_url = get_the_post_thumbnail_url(null, 'large');
        printf(
            '<link rel="preload" as="image" href="%s" fetchpriority="high">' . "\n",
            esc_url($hero_url)
        );
    }
}, 1);

A few rules for preload: use it for one image only — your LCP element. Preloading multiple images dilutes the priority signal and can make things worse. And if your hero is a CSS background-image rather than an <img> tag, consider converting it: background images are discovered only after CSS parses, they can’t take fetchpriority, and they miss out on alt semantics. Semantic <img> tags give you cleaner priority control.

Step 4: Shrink the LCP Resource

Once the browser starts downloading fast, make the download itself smaller:

  • Serve modern formats. WebP images are typically 25–35% smaller than JPEG at the same visual quality. AVIF goes further and is worth using specifically for your hero image. Plugins like ShortPixel, Imagify, or Smush convert your library automatically.
  • Don’t upload bigger than you display. A 4000px-wide hero displayed at 1200px wastes most of its bytes. WordPress generates multiple sizes automatically — make sure your theme is actually using the right one via srcset (block editor and featured images do this natively; custom theme markup may not).
  • Compress sensibly. A JPEG quality of 70–75 cuts file size roughly in half versus quality 90+, with no visible difference on screen. Add this to your theme or a snippet plugin:
add_filter('jpeg_quality', function () { return 75; });

Step 5: Fix Slow Fonts (When LCP Is Text)

If your LCP element is a headline rather than an image, the bottleneck is usually web fonts. A headline can’t render until its font arrives, and Google Fonts served from a third-party domain adds DNS, connection, and download time before the first paint.

The fixes, in order of impact:

  1. Self-host your fonts. Download the woff2 files and serve them from your own domain — one less connection, full control over caching.
  2. Preload the critical weights. Only preload the 1–2 weights actually used above the fold (usually regular and bold).
  3. Use font-display: swap. This lets text render immediately in a fallback font, then swap when the web font arrives — no invisible text waiting on a download.

If text is your LCP, these three steps often move the needle more than any image tweak.

Step 6: Speed Up the Delivery Path

Everything so far assumes the server answers quickly. It doesn’t always:

  • Cut TTFB first. LCP can’t beat a slow server — every millisecond of server response adds directly to LCP. Follow my TTFB reduction guide if your server response is over ~600ms.
  • Use a CDN. If your hero image travels from a single server to a visitor on another continent, no preload hint saves you. A CDN puts the image on an edge server near the visitor.
  • Reduce render-blocking CSS. Heavy page-builder CSS delays everything, including LCP rendering. Tools like WP Rocket’s “Remove Unused CSS” or LiteSpeed Cache’s critical CSS generation help — but always test visually afterward, since aggressive CSS removal can break layouts.

Step 7: Verify With Real Data

After applying your fixes, verify in the right order:

  1. PageSpeed Insights (lab): run the test twice — caching plugins need one run to warm up. Confirm the LCP number dropped and the LCP element is what you expected.
  2. PageSpeed Insights (field data): check the 28-day field data section. Lab scores change instantly; field data takes time as real visitors load the fixed page.
  3. Search Console: the Core Web Vitals report shows which URLs still need work across your whole site, grouped by template — fix the pattern once, not page by page.

A realistic target: get the lab LCP under 2.0s on mobile, which usually translates to under 2.5s in field data once caches warm up.

Quick Reference: The LCP Checklist

  1. Identify the LCP element with DevTools — don’t guess.
  2. Never lazy-load the hero image; use fetchpriority="high".
  3. Preload the LCP image in <head> — one image only.
  4. Convert the hero to WebP or AVIF; serve the right size.
  5. If LCP is text: self-host fonts, preload 1–2 weights, use font-display: swap.
  6. Keep TTFB low and serve images through a CDN.
  7. Verify with lab tests first, field data second.

Slow LCP almost always comes down to one fixable thing: the browser discovering the hero too late, downloading it too slowly, or waiting on something else first. Work through the checklist in order and retest after each change — you’ll know exactly which step made the difference.


Is your WordPress site scoring poorly on Core Web Vitals? I offer speed optimization services for WordPress sites — including LCP, INP, and TTFB fixes — or get in touch for a free performance audit.