All Guides
Technical Performance

Fix LCP Issues

Find your LCP element, optimize it, improve your score.

What this covers: What Largest Contentful Paint (LCP) measures, how to identify your LCP element using Chrome DevTools, and how to fix common causes of slow LCP including unoptimized hero images, render-blocking resources, slow server response, and client-side rendering delays.

Who it’s for: Site owners and developers with LCP scores above 2.5 seconds who need to improve their Core Web Vitals.

Key outcome: You’ll identify your page’s LCP element, understand what’s delaying it, and apply the right optimizations — image compression, preloading, server-side fixes, or caching — to bring LCP under 2.5 seconds.

Time to read: 13 minutes

Part of: Technical Performance series

🔧 Skill Level: Some sections require a developer

You can do: Image optimization, lazy loading plugins, caching plugins
Developer needed for: Server configuration, code-level optimizations, CDN setup

This guide helps you identify and fix the biggest speed bottleneck on your page.

The metric that measures “when does this page actually look ready?”

LCP stands for Largest Contentful Paint. It’s one of Google’s three Core Web Vitals, and it measures something specific: how long until the biggest visible thing on your page finishes loading.

That “biggest visible thing” is your hero image in most cases. Sometimes it’s a large block of text. Sometimes it’s a video thumbnail. Whatever it is, Google’s watching how long it takes to show up.

Why does this matter? Because users don’t care about your server response time or your JavaScript bundle size. They care about one thing: “Can I see what I came here for yet?” LCP is the closest metric we have to measuring that.

What’s Considered Good, Bad, and Ugly

Score What It Means What Users Experience
Under 2.5s Good Page feels fast, content appears quickly
2.5s – 4s Needs improvement Noticeable delay, users start to wonder
Over 4s Poor Frustrating wait, many users leave

Google’s 2021 Page Experience update made this a ranking factor. Not the only one, not the biggest one, but a real one. Sites with good Core Web Vitals get a small edge.

But rankings aside: 53% of mobile users leave a page that takes longer than 3 seconds to load. That’s the real cost of bad LCP.

What Actually Triggers LCP?

LCP looks at the largest element visible in the viewport when the page first loads. It picks ONE element—the biggest one it can see without scrolling.

Common LCP elements:

  • Hero images (the most common by far)
  • Large headline text blocks
  • Video poster images
  • Background images loaded via CSS
  • Featured graphics or illustrations

What’s NOT an LCP element:

  • Anything below the fold (requires scrolling to see)
  • Small icons or logos
  • Decorative elements
  • Content that loads after you interact with the page

How to Find Your LCP Element

Open Chrome DevTools (F12) → Performance tab → hit Record → reload the page → stop recording → look for the “LCP” marker in the timeline. Click it to see exactly which element triggered it.

Or just run PageSpeed Insights. It’ll tell you.

The Four Things That Actually Slow Down LCP

Most LCP problems fall into four categories:

1. The Hero Image Is Too Big

This is the #1 issue. A 3MB hero image will murder your LCP score no matter what else you do.

The fix:





Your hero image

Key points:

  • Use loading="eager" on LCP images (never lazy load your hero)
  • Add fetchpriority="high" to tell the browser this matters
  • Always include width and height to prevent layout shift
  • Serve appropriately sized images (don’t send 4000px images for 800px spaces)

2. The Server Takes Forever to Respond (TTFB)

Time to First Byte measures how long before your server starts sending anything. If TTFB is over 600ms, everything else is waiting.

Common causes:

  • Cheap shared hosting with overloaded servers
  • No server-side caching
  • Slow database queries
  • No CDN (so users far from your server wait longer)

The fix:

  • Upgrade from shared hosting to managed hosting (WP Engine, Kinsta for WordPress)
  • Enable server-side caching
  • Use a CDN (Cloudflare’s free tier is solid)
  • Improve database queries (or just clean up database bloat)

3. Too Much Stuff Blocking the Render

CSS and JavaScript files in your <head> block the page from rendering until they finish loading. Every tracking script, every plugin, every font—they all compete for bandwidth.

The fix:


.hero { height: 100vh; background-size: cover; }
.hero-title { font-size: 3rem; color: white; }

The principle: Show something useful first. Load the fancy stuff after.

4. Fonts Are Blocking Text

Custom fonts can delay text rendering. If your LCP element is a text block and you’re waiting for a web font, that’s a problem.

The fix:


@font-face {
  font-family: 'Your Custom Font';
  src: url('custom-font.woff2') format('woff2');
  font-display: swap; /* Show fallback font immediately, swap when ready */
}

And preload your fonts:

How to Measure LCP

Quick Test: PageSpeed Insights

Go to pagespeed.web.dev, enter your URL, wait 30 seconds. It’ll show you:

  • Your LCP score
  • What element is triggering LCP
  • Specific recommendations to fix it

Test both mobile and desktop. Mobile is worse, and mobile is what most of your visitors use.

Field Data vs Lab Data

Lab data is what PageSpeed Insights simulates—a controlled test on a standard connection.

Field data is what real users actually experience, collected from Chrome browsers (if you have enough traffic).

Field data matters more. It’s in Google Search Console under “Core Web Vitals.”

Real User Monitoring (If You Want to Get Fancy)


import { onLCP } from 'web-vitals';

onLCP((metric) => {
  console.log('LCP:', metric.value, 'ms');

  // Send to your analytics
  gtag('event', 'web_vitals', {
    event_category: 'Performance',
    event_label: 'LCP',
    value: Math.round(metric.value)
  });
});

Or use the built-in browser API:


const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lcp = entries[entries.length - 1];

  console.log('LCP element:', lcp.element);
  console.log('LCP time:', lcp.startTime, 'ms');
});

observer.observe({ type: 'largest-contentful-paint', buffered: true });

WordPress-Specific LCP Fixes

WordPress sites often have LCP problems because of plugin bloat and theme overhead.

Quick wins:


// Add to functions.php

// Remove WordPress junk from <head>
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');

// Preload hero image on homepage
add_action('wp_head', function() {
  if (is_front_page()) {
    $hero = get_template_directory_uri() . '/images/hero.webp';
    echo '<link rel="preload" as="image" href="' . esc_url($hero) . '">';
  }
});

// Add fetchpriority to featured images
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment, $size) {
  if (is_front_page() && $size === 'large') {
    $attr['fetchpriority'] = 'high';
  }
  return $attr;
}, 10, 3);

Plugin cleanup:

  • Deactivate and delete unused plugins
  • Use conditional loading (only load Contact Form 7 on your contact page)
  • Use WP Rocket or LiteSpeed Cache for automated improvement

Mobile LCP (It’s Worse)

Mobile users have slower processors and often slower connections. Your LCP is probably 2-3x worse on mobile than desktop.

Mobile-specific fixes:



Hero

// Reduce quality on slow connections (Chromium only; uses optional chaining for other browsers)

if (navigator.connection?.effectiveType === '2g' ||
    navigator.connection?.effectiveType === 'slow-2g') {
  // Serve lower-quality images
  document.querySelectorAll('img[data-src-low]').forEach(img => {
    img.src = img.dataset.srcLow;
  });
}

Debugging When It’s Not Working

“I optimized my hero image but LCP didn’t improve”

  • Check what PageSpeed Insights says is your LCP element now—it will have changed
  • Your server response time will be the bottleneck
  • Render-blocking resources will be the issue, not the image

“LCP was good, now it’s bad”

  • Did you add a new plugin or script?
  • Did your hosting change?
  • Did a theme update happen?
  • Check your CDN configuration

Finding the exact LCP element:


const observer = new PerformanceObserver((list) => {
  const lcp = list.getEntries().pop();

  console.log('LCP Time:', lcp.startTime);
  console.log('Element:', lcp.element);
  console.log('Tag:', lcp.element?.tagName);
  console.log('Class:', lcp.element?.className);

  if (lcp.element?.tagName === 'IMG') {
    console.log('Image src:', lcp.element.src);
  }
});

observer.observe({ type: 'largest-contentful-paint', buffered: true });

The Checklist

Before you do anything else:

  • Run PageSpeed Insights on your homepage (mobile)
  • Identify your LCP element (it tells you)
  • If it’s an image: compress it, use WebP, add fetchpriority="high"
  • If TTFB is slow: upgrade hosting or add caching
  • If render-blocking resources are the issue: defer JavaScript, inline critical CSS
  • Test again

That’s it. LCP improvement isn’t complicated—it’s just tedious. Find the bottleneck, fix it, move on.

LCP Questions Answered

What is a good LCP score?

Good: under 2.5 seconds. Needs improvement: 2.5-4 seconds. Poor: over 4 seconds. These thresholds apply to the 75th percentile of page loads—meaning 75% of your visitors should experience LCP under 2.5s.

What usually causes slow LCP?

The top causes: unoptimized hero images (too large, wrong format), slow server response time, render-blocking JavaScript, and web fonts that delay text display. Hero images are the culprit in about 70% of cases.

Does LCP affect SEO rankings?

Yes. LCP is one of three Core Web Vitals that Google uses as ranking signals. Poor LCP can hurt rankings, especially on mobile where competition is tight. But content relevance still matters more than speed alone.

How do I find my LCP element?

In Chrome DevTools: Performance panel → record a page load → click the LCP marker in the timeline. Or use PageSpeed Insights—it identifies the LCP element and shows what’s delaying it.

Sources

  • Google Web Keys: LCP – Official definition and thresholds
  • Improve LCP – Google’s improvement guide
  • Core Web Vitals Report – Google Search Console documentation
  • web-vitals JavaScript library – For real user monitoring

Confirming LCP Is Under 2.5 Seconds

  • PageSpeed Insights shows LCP under 2.5 seconds on mobile
  • Search Console’s Core Web Vitals report shows “Good URLs” increasing
  • Field data (CrUX) confirms real users experience fast LCP
  • Your hero image loads visibly within 2 seconds on a throttled connection

Tip: Lab data (PageSpeed Insights) can differ from field data (real users). Both matter, but field data is what Google uses for rankings.

✓ Your LCP Issues Are Resolved When

  • Largest Contentful Paint is under 2.5 seconds in PageSpeed Insights field data (75th percentile)
  • The LCP element is identified and preloaded (either via <link rel=”preload”> or fetchpriority=”high”)
  • Server response time (TTFB) for the HTML document is under 800ms
  • No render-blocking CSS or JS delays the LCP element from painting
  • LCP image or text is visible without waiting for JavaScript execution

Test it: Run Lighthouse on mobile, note the LCP element and time, then check PageSpeed Insights field data — both lab and field LCP should be under 2.5s.