Fix & Identify Largest Contentful Paint (LCP) issues

Learn how to debug and fix all Largest Contentful Paint related issues on your page

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2025-07-21

A Consultant's Guide to Diagnosing and Fixing LCP

My name is Arjen Karel, and I'm a page speed consultant. Over the years, I've audited hundreds of websites, and one of the most persistent challenges is Largest Contentful Paint (LCP). In this guide, I'll share the exact methodology I use to diagnose and resolve LCP issues. You'll see mentions of CoreDash, a RUM tool I created to get the precise data needed for this process. The principles here are universal, but I believe in showing real examples from the tools I build and use daily.

Improving LCP is a systematic process of elimination. By following a clear methodology, you can effectively diagnose the bottlenecks in your page load process and apply targeted fixes to improve your site's performance and user experience.

The Diagnostic Methodology: Field Data First, Lab Data Second

To optimize effectively, you must adopt a two-step diagnostic workflow. This ensures you are solving problems your users are actually facing, not just chasing scores in a lab environment.

  1. Field Data (RUM & CrUX) shows you WHAT is happening. Field data is collected from real users visiting your site [1]. It tells you if you have an LCP problem, which pages are affected, and which users (mobile or desktop) are experiencing it. You must always start here to confirm a real problem exists.
  2. Lab Data (Lighthouse, DevTools) helps you diagnose WHY it's happening. Lab data is collected in a controlled, simulated environment [2]. Once your field data has confirmed a problem on a specific page, you can use lab tools to consistently replicate the issue and dissect the loading process to find the root cause.

Starting with field data ensures your optimization efforts are focused on changes that will have a measurable impact on your actual users.

Key Terminology

  • Field Data: Also known as Real User Monitoring (RUM), this is performance data collected from actual users in diverse, real-world conditions (varying devices, network speeds, and locations).
  • Lab Data: Performance data collected within a controlled, consistent environment using tools like Lighthouse. It is ideal for debugging and testing changes, but does not always reflect real-user experience.
  • CrUX: The Chrome User Experience Report. A public dataset from Google that contains field data from millions of Chrome users. It powers the Core Web Vitals report in Google Search Console.
  • TTFB (Time to First Byte): The time between the browser requesting a page and when it receives the very first byte of the HTML response. It is a measure of server responsiveness.

Step 1: Identify LCP Issues with Field Data

Your first task is to use real-user data to confirm which pages, if any, have a poor LCP.

An Accessible Starting Point: Google Search Console

A valid place to start is the Core Web Vitals report in Google Search Console. Log in, navigate to the report, and review the mobile and desktop charts. If Google is flagging URLs with "LCP issue: longer than 2.5s," you have confirmation from the Chrome User Experience (CrUX) Report that a percentage of your users are having a poor experience.

While Search Console is invaluable for confirming a problem, it's slow to update and groups data by URL patterns. For more immediate and granular insights, a dedicated RUM tool is required.

Google Search Console showing Core Web Vitals LCP issues.

A Deeper Look: Real User Monitoring (RUM)

To get the ground truth, you can track LCP for every user on every page load using a Real User Monitoring (RUM) solution. While you can build your own by leveraging the web-vitals library to send data to your analytics backend, this can be a significant engineering effort.

Alternatively, dedicated RUM tools are designed for this purpose. Tools like CoreDash are built to provide this data out of the box. Setting it up typically involves adding a small JavaScript snippet to your site's header. Once installed, it begins collecting performance data from every real visitor.

A good RUM tool helps you move beyond URL groups to understand:

  • Your precise LCP score for any specific URL.
  • A breakdown of every LCP element (e.g., an image, a headline) and which ones are most frequently associated with a slow LCP.
  • The exact timing for each of the four LCP phases for every page view, pinpointing the bottleneck.

On a recent audit for an e-commerce client, we saw high LCP values on product pages despite a fully optimized hero image. Our RUM data revealed the delay was not the image itself, but a client-side A/B testing script that was dynamically changing the product title, which was the LCP element. This script blocked rendering long enough to push LCP into the "poor" category. Pausing the test immediately resolved the issue, proving that LCP optimization requires looking beyond just the LCP element itself.

For example, in CoreDash, you can navigate to the LCP page and view a data table that shows your slowest LCP elements. By clicking on a specific element (like a particular CSS class for a hero image), you can filter all the metrics to see the performance data just for pages where that element was the LCP.

CoreDash showing a breakdown of LCP scores by element.

Whether you use a custom solution or a tool like CoreDash, the goal is the same: use field data to find your slowest page and identify its most common LCP element. Once you have that target, you're ready to diagnose.

Step 2: Diagnose the Bottleneck with Lab Tools

Now that you know which page to fix, it's time to figure out why it's slow. This is where a lab tool like PageSpeed Insights or the Lighthouse panel in Chrome DevTools becomes essential [3].

Run a test on your target URL. In the report, scroll down to the "Diagnostics" section and find the "Largest Contentful Paint element" audit. This waterfall chart breaks down your LCP time into its four sub-parts. Your RUM tool should show a similar breakdown based on your field data.

A chart showing the four phases of LCP: TTFB, Load Delay, Load Time, and Render Delay.

Your goal is to find the longest phase in this breakdown. That's your primary bottleneck, and that's where you should focus your optimization efforts first.

Step 3: Understanding the Real Bottleneck

In most real-world scenarios, the most significant and persistent LCP problems come from one of the other three phases.

  • Time to First Byte (TTFB): This is the unskippable foundation. A slow server response is a direct, millisecond-for-millisecond addition to your LCP. Before you optimize a single image, you must ensure your server is responding quickly.
  • Resource Load Delay: This is the "discovery problem" and one of the most common issues. The browser can't download a resource it doesn't know about. If your LCP image is hidden in a CSS or JavaScript file, or even if it's in the HTML but other resources are requested first, the browser finds it too late, wasting valuable time.
  • Element Render Delay: This is the "too busy to paint" problem. The LCP image file might be fully downloaded, but if the browser's main thread is blocked by heavy JavaScript execution, it simply can't get around to painting the image on the screen.

The following guide is structured to tackle these phases in a logical order. Always start by ensuring your TTFB is fast and your LCP resource is discoverable before moving on to file size and render optimizations.

Step 4: Execute the Fix

With the bottleneck identified, you can apply targeted optimizations. The way you implement these fixes will depend heavily on your site's architecture. We'll first cover the universal principles for each phase, then provide specific advice for WordPress and modern JavaScript frameworks.

1. Optimizing Time to First Byte (TTFB)

If your TTFB is slow (a good target is under 800ms [4]), it sets a high floor for your LCP. Improving TTFB will improve every other loading metric. This is the time it takes for the browser to receive the first byte of HTML from your server.

Diagram highlighting the Time to First Byte portion of the LCP timeline.

Universal TTFB Solutions

  • Enable Caching: This is one of the most effective ways to improve TTFB. Caching generates and stores a copy of the page so it can be served instantly without waiting for the server to build it from scratch on every visit.
  • Use a CDN: A Content Delivery Network serves your content from a server physically close to your user, which reduces network latency [5]. Caching your full HTML pages at the CDN's edge is a powerful strategy for a fast, global TTFB.
  • Use Brotli or Gzip Compression: Ensure your server is compressing text-based assets like HTML, CSS, and JavaScript. Brotli offers better compression than Gzip and should be preferred.
  • Use HTTP/3 with 0-RTT: Ensure your server is configured to use HTTP/3. It offers significant performance advantages, including better multiplexing. Crucially, it supports 0-RTT (Zero Round Trip Time Resumption), which eliminates the connection setup time for repeat visitors, providing an instant TTFB boost [6].
  • Use 103 Early Hints: For an advanced boost, use the 103 Early Hints status code. This allows your server or CDN to send hints about critical CSS and JS files to the browser while it's still preparing the full HTML document, allowing downloads to start even sooner [7]. This is a powerful server-level feature that can benefit any platform.

Platform-Specific TTFB Fixes

On WordPress:
  • Invest in Quality Hosting: On WordPress, slow TTFB is often related to the hosting environment. Cheap, shared hosting can be a bottleneck. Consider a managed WordPress host that is optimized for performance.
  • Use a Caching Plugin: A high-quality caching plugin (e.g., WP Rocket, W3 Total Cache) is non-negotiable. It handles the generation of static HTML files for you, which is the core of effective caching on this platform.
On a JS Framework:
  • Choose the Right Hosting Platform: For Node.js applications, platforms like Vercel or Netlify are highly optimized for SSR/SSG frameworks and offer intelligent caching and serverless function execution out of the box.
  • Implement SSR Caching: If you're using Server-Side Rendering, cache the rendered pages on the server (e.g., using Redis or an in-memory cache) to avoid re-rendering on every request.
  • Beware of Serverless Cold Starts: If using serverless functions for rendering, be aware that a "cold start" (the first request after a period of inactivity) can have a high TTFB. Use provisioned concurrency or keep-alive strategies to mitigate this.

2. Reducing Resource Load Delay

This is frequently the largest bottleneck. It means the browser was ready to work, but it couldn't find your main image or font file right away. This delay is typically caused by one of two problems: the resource is discovered late, or it's given a low download priority.

Diagram highlighting the Resource Load Delay portion of the LCP timeline.

Universal Load Delay Solutions

The universal solution to Resource Load Delay is to ensure your LCP resource is both discoverable in the initial HTML markup and given a high priority by the browser. Here’s how to achieve that:

  • Make the LCP Resource Discoverable: The most important step is to ensure your LCP element is present in the HTML that the server sends. Browsers use a high-speed "preload scanner" to look ahead in the raw HTML for resources like images and scripts to download. If your LCP image is loaded via a CSS `background-image` or injected with JavaScript, it's invisible to this scanner, causing a major delay. The most robust solution is always to use a standard <img> tag with a `src` attribute in your server-rendered HTML.
  • Control the Load Order with `preload`: If you cannot make the LCP resource directly discoverable (a common issue with fonts or CSS background images), the next best solution is to use <link rel="preload">. This tag acts as an explicit instruction in your HTML <head>, telling the browser to start downloading a critical resource much earlier than it would have found it naturally. This is essential for changing the absolute load order, ensuring your LCP image or font is enqueued before less critical resources like asynchronous JavaScript files.
  • Ensure High Priority with `fetchpriority`: Even when a resource is discoverable, the browser might not give it the highest download priority. Adding fetchpriority="high" to your <img> tag or your <link rel="preload"> tag is a powerful hint to the browser that this specific resource is the most important one for the user experience, helping it win the race for bandwidth against other resources [8].

Platform-Specific Load Delay Fixes

On WordPress:
  • Avoid Page Builder Background Images: Many page builders make it easy to set a hero image as a CSS `background-image` on a `div`. This makes it invisible to the browser's preload scanner. If possible, use a standard `` block instead. If not, you may need a plugin or custom code to `preload` that specific image.
  • Disable Lazy-Loading for the LCP Image: Many optimization plugins will automatically lazy-load all images. You must find the setting in your plugin to exclude the LCP image (and often the first few images on the page) from being lazy-loaded.
On a JS Framework:
  • Use Server-Side Rendering (SSR): This is often the most impactful fix. A default Client-Side Rendered (CSR) React app sends minimal HTML, and the LCP element only exists after a large JS bundle is downloaded and executed. SSR frameworks like Next.js or Remix deliver the complete HTML, including the `` tag, so the browser can discover it immediately.
  • Use Framework-Specific Image Components: Frameworks like Next.js offer an ` ` component with a `priority` prop. Using ` ` automatically applies `fetchpriority="high"` and other optimizations to your LCP image.

3. Decreasing Resource Load Time

Ensuring your LCP resource is as small as possible is still a crucial part of the process. This phase is about how long it takes to download the LCP resource file over the network.

Diagram highlighting the Resource Load Time portion of the LCP timeline.

Universal Load Time Solutions

  • Reduce File Size with Modern Formats and Responsive Images: The most direct way to shorten download time is to make the file smaller. For images, this means using modern, highly-efficient formats like AVIF or WebP [9]. Critically, you must also serve responsive images using the <picture> element or the srcset and sizes attributes. This ensures that a user on a mobile device receives an image appropriately sized for their smaller screen, rather than being forced to download a massive desktop-sized image. A 400-pixel wide mobile screen simply doesn't need a 2000-pixel wide image file. For text-based LCPs, ensure your fonts are in the efficient WOFF2 format and are subsetted to remove unused characters.
  • Reduce Network Contention: The LCP resource has to compete for the user's limited network bandwidth. Deferring non-critical resources, like analytics scripts or CSS for below-the-fold content, frees up bandwidth so the browser can focus on downloading the LCP resource faster.
  • Host Critical Resources on Your Main Domain: Avoid loading your LCP resource from a different domain if possible. Setting up a new connection to another server adds time-consuming DNS lookups and handshakes.

Platform-Specific Load Time Fixes

On WordPress:
  • Use an Image Optimization Plugin: Tools like ShortPixel or Smush can automatically compress images on upload, convert them to modern formats like WebP/AVIF, and generate responsive `srcset` sizes.
  • Manually Resize Images: Before uploading, resize your images to be no larger than they need to be. Don't upload a 4000px wide image for a space that is only 1200px wide on the largest screens.
On a JS Framework:
  • Use an Image CDN: This is a powerful solution. Services like Cloudinary, Imgix, or Akamai's Image & Video Manager can automate the entire optimization process. You upload one high-quality image, and they deliver a perfectly sized, compressed, and formatted version to each user via a fast CDN.
  • Leverage Build Tools: When you `import` an image into a component in a modern framework, the build tool (like Webpack or Vite) can automatically hash and optimize the file as part of the build process.

4. Shortening Element Render Delay

The resource has finished downloading, but it's not on the screen yet. This means the browser's main thread is busy with other tasks and can't paint the element. This is another very common and significant bottleneck.

Diagram highlighting the Element Render Delay portion of the LCP timeline.

Universal Render Delay Solutions

  • Defer or Remove Unused JavaScript: Any JS that isn't essential for rendering the initial, visible part of the page should be deferred using the defer or async attributes.
  • Use Critical CSS: A large, render-blocking stylesheet can delay rendering. The critical CSS technique involves extracting the minimum CSS needed to style the above-the-fold content, inlining it in the <head>, and loading the rest of the styles asynchronously [10].
  • Break Up Long Tasks: A long-running script can block the main thread for an extended period, preventing rendering. This is also a primary cause of poor Interaction to Next Paint (INP). Break up your code into smaller, asynchronous chunks that yield back to the main thread.

Platform-Specific Render Delay Fixes

On WordPress:
  • Audit Your Plugins: Too many plugins, especially heavy ones like sliders or complex page builders, can add significant CSS and JS that blocks the main thread. Deactivate plugins one by one to identify performance hogs.
  • Use a Lightweight Theme: A bloated theme with dozens of features you don't use can be a major source of render-blocking code. Choose a performance-focused theme.
  • Use Plugin Asset Managers: Tools like Asset CleanUp or Perfmatters allow you to conditionally disable CSS and JS from specific plugins on pages where they are not needed.
On a JS Framework:
  • Code Splitting is Key: Don't ship all your app's JavaScript in one giant bundle. Split your code by route (so users only download the code for the page they are visiting) and by component.
  • Lazy Load Components: Use `React.lazy` and `Suspense` to lazy-load components that are not immediately visible (e.g., components below the fold or in modals). This keeps them out of the initial bundle.

Advanced: Optimizing LCP for Subsequent Navigations

Fixing the initial LCP is crucial, but you can create a dramatically faster experience for users as they browse your site by optimizing for subsequent page loads.

Ensure Pages are Eligible for the Back/Forward Cache (bfcache)

The bfcache is a browser optimization that stores a complete snapshot of a page in memory when a user navigates away. If they click the back button, the page can be restored instantly, resulting in a near-zero LCP. Many pages are ineligible for this cache due to things like `unload` event listeners. Use the Lighthouse "bfcache" audit to test your pages and remove any blocking features [11].

Use the Speculation Rules API for Prerendering

The Speculation Rules API is a new, powerful tool that allows you to declaratively tell the browser which pages a user is likely to navigate to next. The browser can then fetch and pre-render these pages in the background. When the user clicks a link to a prerendered page, the navigation is instantaneous, leading to a phenomenal user experience and a near-zero LCP [12]. You can define these rules in a `<script type="speculationrules">` tag in your HTML.

<script type="speculationrules"> 
 { 
  "prerender": [{ 
   "source": "document", 
   "where": { 
    "href_matches": "/products/*" 
   }, 
   "eagerness": "moderate" 
  }] 
 } 
 </script>  

This example tells the browser to look for links on the current page that go to product pages and to start prerendering them when a user hovers over the link.

By methodically working through these four phases and considering advanced navigation optimizations, you can pinpoint the exact cause of your LCP issues and apply the correct, high-impact fix.

References

  1. web.dev: Lab and field data
  2. Chrome for Developers: Debug Web Vitals in the field
  3. web.dev: Optimize Largest Contentful Paint
  4. web.dev: Optimize for a good TTFB
  5. Cloudflare: What is a CDN?
  6. web.dev: HTTP/3
  7. web.dev: Slower is faster? Sending an HTTP 103 response to speed up your site
  8. web.dev: Optimize LCP with fetchpriority
  9. web.dev: Use modern image formats
  10. web.dev: Extract critical CSS
  11. web.dev: Back/forward cache
  12. web.dev: Speculation Rules API

Need your site lightning fast?

Join 500+ sites that now load faster and excel in Core Web Vitals.

Let's make it happen >>

  • Fast on 1 or 2 sprints.
  • 17+ years experience & over 500 fast sites
  • Get fast and stay fast!
Fix & Identify Largest Contentful Paint (LCP) issuesCore Web Vitals Fix & Identify Largest Contentful Paint (LCP) issues