Core Web Vitals

How to Fix LCP in WordPress: Reduce Largest Contentful Paint

Jamie McKaye
Jamie McKaye
8 min read
How to Fix LCP in WordPress: Reduce Largest Contentful Paint

Key Takeaways

  • LCP measures when the largest visible element finishes rendering — usually a hero image, heading, or video poster
  • The threshold is 2.5 seconds — anything over is “Poor” and will affect your Google rankings
  • The four main causes of poor LCP: slow server response (TTFB), render-blocking resources, slow resource load times, and client-side rendering
  • Preloading your LCP image with <link rel=”preload”> and fetchpriority=”high” is the single highest-impact quick fix
  • Never lazy load your LCP element — this is the most common mistake we see

Get Your Free Audit →

What is LCP and why it matters

Largest Contentful Paint measures the moment the biggest visible content element finishes rendering in the viewport. It’s one of three Core Web Vitals that Google uses as a ranking signal — and it’s the one most WordPress sites fail first. LCP answers the most fundamental user question: “Has the page actually loaded?”

The threshold is clear: under 2.5 seconds is good, 2.5–4.0 seconds needs improvement, and over 4.0 seconds is poor. Google measures LCP using real user data from the Chrome User Experience Report (CrUX), not lab tests. Your 75th percentile needs to hit 2.5 seconds or better. As we explain in our complete Core Web Vitals guide, field data is what determines your ranking impact.

The business impact is immediate. LCP is the metric visitors feel most directly — a slow LCP means staring at a blank or half-loaded page, which drives bounce rates through the roof. We’ve seen bounce rates drop 25-30% when LCP goes from 4 seconds to under 2.5 seconds. It’s important to understand that LCP is a Core Web Vital, not a PageSpeed metric — the distinction matters when you’re debugging.

How to identify your LCP element

Before you can fix LCP, you need to know what your LCP element is. It’s not always what you’d expect.

Browser DevTools highlighting the Largest Contentful Paint element on a webpage with timing measurements
Chrome DevTools identifies your LCP element — usually the hero image or largest heading. This is the element you need to optimise.

Open Chrome DevTools (F12), go to the Performance tab, and record a page load. In the Timings section, you’ll see an “LCP” marker. Click it and it’ll highlight the element in the DOM. Common LCP elements include:

  • Hero images — The large banner or header image above the fold
  • Featured images — Blog post or product featured images
  • Heading text — The <h1> element if there’s no large image
  • Video poster images — The thumbnail shown before a video plays
  • Background images via CSS — Hero sections using background-image

You can also use PageSpeed Insights — it shows the LCP element in the diagnostics section. The key insight is that your LCP element may differ between mobile and desktop. On mobile, the LCP element is often a heading because the hero image may be below the fold, while on desktop the hero image is almost always the LCP element.

Fix #1: Reduce TTFB — the foundation of LCP

Time to First Byte is the starting point for LCP. Your browser can’t start rendering content until it receives the first byte of the HTML response. If your server takes 800ms to respond, your LCP can never be under 800ms — it’s physically impossible.

Before and after LCP optimisation showing slow TTFB and render-blocking resources versus optimised loading with preloaded LCP image
Before: slow TTFB, render-blocking resources, and late LCP image load. After: fast server, no blocking resources, preloaded LCP image.

TTFB directly affects LCP in a linear relationship. Every millisecond of TTFB adds directly to your LCP time. Here’s the rough breakdown of a typical LCP measurement:

  • TTFB: time for server to respond
  • HTML download time
  • Resource discovery (browser finds the LCP image in the HTML)
  • Resource download time (image downloads)
  • Render time (browser paints the element)

Target TTFB under 200ms. You achieve this through server-level caching (Varnish, Nginx FastCGI cache, or Cloudflare edge caching), PHP version upgrades (PHP 8.2+ is 30-50% faster than 7.4), and proper hosting infrastructure. Shared hosting with TTFB over 500ms will make it nearly impossible to pass LCP without edge caching.

Fix #2: Eliminate render-blocking resources

When a browser encounters a <link rel="stylesheet"> or <script> tag in the <head>, it stops rendering until that resource downloads and executes. If you have 8 CSS files and 5 JavaScript files loading synchronously in the head, nothing renders until all 13 resources are downloaded and processed.

The fixes, in order of impact:

Inline critical CSS. Extract the CSS needed for above-the-fold rendering and inline it directly in the <head> via a <style> tag. This eliminates the network request for above-fold styles. Load the full stylesheet asynchronously using <link rel="preload" as="style">.

Defer non-critical JavaScript. Add the defer attribute to script tags that don’t affect above-fold rendering. This tells the browser to download the script but not execute it until after HTML parsing is complete. WordPress loads jQuery and numerous plugin scripts synchronously by default — deferring these can cut hundreds of milliseconds off LCP.

Remove unused CSS and JS. Use Chrome DevTools Coverage tab (Ctrl+Shift+P → “Coverage”) to identify how much of each file is actually used. Most WordPress themes deliver 300-500KB of CSS but only use 20-30% on any given page. Perfmatters and Asset CleanUp can disable unused plugin assets on a per-page basis.

Fix #3: Optimise the LCP resource

Once render-blocking resources are handled, focus on making the LCP element itself load as fast as possible. This is where your hero image is usually your LCP element, and optimising it delivers the biggest single improvement.

Preload the LCP image. Add this to your <head>:

<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">

The fetchpriority="high" attribute tells the browser to prioritise this resource above all others. Without preloading, the browser doesn’t discover the LCP image until it parses the HTML and finds the <img> tag — which can be hundreds of milliseconds into the page load.

Use WebP or AVIF format. Convert hero images to WebP (30% smaller than JPEG at equivalent quality) or AVIF (50% smaller). A 200KB JPEG hero image becomes 140KB in WebP or 100KB in AVIF — that’s 60-100KB less to download.

Serve responsive images. Use the srcset and sizes attributes to serve appropriately sized images for each viewport. A mobile user shouldn’t download a 1920px-wide hero image when they only need 750px wide.

Never lazy load the LCP element. This is the single most common LCP mistake. Lazy loading delays image loading until the element enters the viewport — but the LCP element is already in the viewport on page load. Adding loading="lazy" to your hero image can add 1-2 seconds to LCP. WordPress automatically adds lazy loading to all images — you need to explicitly remove it from above-fold images.

Fix #4: Fix client-side rendering issues

Some WordPress setups render content via JavaScript rather than server-side HTML. This adds a delay because the browser must download, parse, and execute JavaScript before the LCP element even exists in the DOM.

Common culprits on WordPress:

  • Elementor’s frontend JavaScript that initialises slider/carousel hero sections
  • React-based blocks that render content client-side in the Gutenberg editor
  • AJAX-loaded content that fetches hero sections dynamically
  • JavaScript-dependent hero images (images set via JS rather than HTML <img> tags)

The solution: ensure your LCP element is in the initial HTML response, not rendered by JavaScript. If your hero section relies on JavaScript, consider server-side rendering the initial state and then enhancing with JavaScript after load.

WordPress-specific LCP issues

Here are the WordPress-specific LCP problems we encounter most frequently:

Elementor hero sections. Elementor often loads hero images as CSS background images, which the browser discovers late. The fix: use a regular <img> tag instead and preload it. If you must use a background image, add a <link rel="preload"> in the head.

WooCommerce product images. The main product image is typically the LCP element on product pages. WooCommerce’s default image gallery loads images via JavaScript (Flexslider/PhotoSwipe), delaying LCP. Disable the gallery JavaScript for the main image and load it as a standard <img> with fetchpriority="high".

Revolution Slider / slider plugins. Any slider plugin that loads images via JavaScript will destroy LCP. The first slide should be rendered as a standard HTML image, with subsequent slides loaded by the slider script. Better yet, remove the slider entirely — they convert poorly and always hurt performance.

WordPress’s default lazy loading. Since WordPress 5.5, all images get loading="lazy" automatically. WordPress 6.3+ includes a fix that skips lazy loading on the first content image, but it’s not always accurate. Explicitly set loading="eager" on your LCP image and add fetchpriority="high".

Testing and verifying your LCP improvement

After implementing fixes, verify your improvements using multiple tools:

  1. PageSpeed Insights — Run 3-5 tests and take the median. Lab scores fluctuate, so a single test isn’t reliable.
  2. Chrome DevTools Performance tab — Record a page load and check the LCP timing marker. This gives you the most accurate single-measurement result.
  3. WebPageTest.org — Test from multiple locations and connections. The filmstrip view shows you exactly when the LCP element appears.
  4. Search Console — Wait 28 days after your changes for field data to reflect improvements. This is the ultimate measure of success.

Set up ongoing monitoring to catch regressions. Plugin updates, content changes, and third-party script modifications can all affect LCP without warning. Our guide to monitoring your Core Web Vitals over time covers the complete setup.

What is a good LCP score for WordPress?

Google considers LCP under 2.5 seconds as “Good”. However, we target under 1.5 seconds for our clients because it provides a comfortable buffer and delivers noticeably better user experience. Most WordPress sites we optimise achieve LCP between 0.8–1.5 seconds on mobile.

Does lazy loading hurt LCP?

Only if applied to the LCP element. Lazy loading above-fold images — especially your hero image — adds 1-2 seconds to LCP because the browser waits until the image enters the viewport before starting to download it. The fix: add loading=”eager” and fetchpriority=”high” to your LCP image. Lazy load everything else.

How do I find my LCP element?

Use Chrome DevTools: open the Performance tab, record a page load, and look for the “LCP” marker in the Timings section. Click it to highlight the element. Alternatively, PageSpeed Insights shows the LCP element in the diagnostics section. Note that LCP elements can differ between mobile and desktop viewports.

Can I fix LCP without changing my hosting?

Sometimes. If your TTFB is already under 400ms, the other fixes (preloading, render-blocking removal, image optimisation) can bring LCP under 2.5 seconds. But if your TTFB is over 600ms, no amount of frontend optimisation will compensate. In that case, you need either better hosting or edge caching via Cloudflare to reduce TTFB at the network level.

Does CDN help with LCP?

Yes, significantly. A CDN reduces the download time for your LCP resource (images, fonts) by serving it from a geographically closer edge node. Cloudflare’s edge caching can also reduce TTFB to under 50ms by caching the entire HTML response. Both improvements directly reduce LCP. For WordPress specifically, Cloudflare APO is one of the most impactful single changes you can make.

JM

Jamie McKaye

Founder of VeloPress. 18 years in SEO and web performance. Optimised 150+ WordPress sites to score 95–100 on PageSpeed Insights.

Jamie McKaye

Jamie McKaye
Founder, VeloPress

18 years in digital marketing, SEO, and web performance. Optimised 150+ WordPress sites to achieve near-perfect Core Web Vitals scores.

LCP still over 2.5 seconds?

We’ll fix your LCP — guaranteed

Our free audit identifies your exact LCP bottleneck and we fix it as part of our performance optimisation service. Score guarantee: 90+ or you don’t pay.

Get Your Free Audit →
View Pricing
Jamie McKaye

Jamie McKaye

Founder, VeloPress

Founder of VeloPress. 18 years in digital marketing, SEO, and web performance engineering. Optimised 150+ WordPress sites to score 95-100 on PageSpeed Insights. Based in Surrey, UK.

Get Started

Still struggling with WordPress speed?

VeloPress fixes this every day. We'll diagnose exactly what's slowing your site down and build a plan to hit 90+ on PageSpeed Insights.

Get Your Free Audit View Pricing

See what a full audit looks like — view sample report