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:
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:
// 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.