Largest Contentful Paint: How to Fix Your Biggest Speed Bottleneck
If your website takes more than 2.5 seconds to show users the main content on the page, Google considers your user experience poor. That metric (the time until the largest visible element renders) is called Largest Contentful Paint, and it’s the Core Web Vital that trips up the most sites.
We see it constantly. A business owner runs their site through PageSpeed Insights, sees a red LCP score, and doesn’t know what to do with it. The suggestions Google offers are vague. “Reduce server response time.” “Eliminate render-blocking resources.” “Preload key requests.” What does any of that actually mean in practice? If you would rather see how it all fits together, we wrote the website performance checklist we work through on every build.
This post breaks down what causes poor LCP, what elements trigger it, and the specific fixes for each cause. No theory, just the things that move the needle.
What LCP Actually Measures
LCP measures how long it takes for the largest content element within the viewport to fully render. Not the entire page, just the biggest thing a user sees without scrolling.
Google’s thresholds are clear:
LCP is measured from when the page first starts loading (navigation start) until the largest content element is fully painted on screen. It’s a user-centric metric: it measures what the user perceives, not what’s happening under the hood.
What Elements Trigger LCP
The LCP element varies by page, but it’s almost always one of these:
Hero Images
The most common LCP element by far. That large banner image at the top of your homepage (the one with your business photo or a background behind your headline) is probably your LCP element. If it’s 2MB, unoptimized, and loaded lazily, your LCP will suffer.
Large Heading Text
On pages without a large image above the fold, the H1 heading is often the LCP element. This is usually the easiest case: text renders fast as long as fonts load quickly and nothing blocks rendering.
Video Poster Images
If you have a background video or hero video, the poster image (the still frame shown before the video plays) is the LCP element. Many sites either don’t set a poster image (causing a blank space until the video loads) or set one that’s massive and unoptimized.
Featured Images on Blog Posts
The thumbnail or featured image at the top of blog post content frequently triggers LCP on article pages.
Background Images Set via CSS
Large CSS background images on hero sections can be LCP elements, but they’re trickier because browsers can’t discover them until the CSS file is parsed. This adds a discovery delay that HTML <img> tags don’t have.
How to identify your LCP element: Run your page through PageSpeed Insights and scroll to the LCP diagnostic. It will tell you exactly which element triggered LCP and how long it took. Chrome DevTools’ Performance panel also shows the LCP element in its timeline.

Common Causes of Poor LCP and How to Fix Each
Cause 1: Slow Server Response Time (TTFB)
If your server takes 2 seconds to respond, your LCP can’t possibly be under 2.5 seconds. Time to First Byte (TTFB) is the floor for all other metrics.
Why it happens:
- Shared hosting with overloaded servers
- No server-side caching (every request rebuilds the page from scratch)
- Slow database queries
- Unoptimized WordPress installations with too many plugins
- Server located far from your users
Fixes:
- Enable page caching. This is the single most impactful fix for WordPress sites. A caching plugin like WP Rocket or LiteSpeed Cache serves pre-built HTML instead of generating pages dynamically. TTFB drops from seconds to milliseconds.
- Upgrade hosting. Move from shared hosting to managed WordPress hosting (Cloudways, Kinsta, WP Engine) or a VPS. We’ve seen TTFB improvements of 70-80% from hosting upgrades alone.
- Use a CDN. Cloudflare or similar CDN serves cached pages from edge servers near your users. A visitor in St. Louis gets your site from a St. Louis edge server, not your origin server in Dallas.
- Reduce plugin bloat. Each WordPress plugin can add database queries and processing time. Audit your plugins. Deactivate anything you’re not actively using. We regularly find clients running 30+ plugins when 12 would do.
Target: TTFB under 800 milliseconds. Under 200 milliseconds with caching is achievable and common.
Cause 2: Render-Blocking Resources
Before the browser can paint your LCP element, it has to download and process all CSS and synchronous JavaScript in the <head> of your document. If you have 500KB of CSS and 400KB of JavaScript blocking render, the browser is waiting for all of that before showing users anything.
Why it happens:
- Large, monolithic CSS files that include styles for every page on the site
- Third-party scripts loaded synchronously (analytics, chat widgets, tag managers)
- Font stylesheets blocking render until fonts download
- JavaScript that doesn’t need to run before the page is visible
Fixes:
- Inline critical CSS. Extract the CSS needed to render above-the-fold content and inline it directly in the HTML
<head>. Load the rest of the CSS asynchronously. Tools like Critical or WP Rocket’s “Remove Unused CSS” feature automate this. - Defer JavaScript. Add
deferorasyncattributes to script tags that don’t need to execute before the page renders. Most third-party scripts (analytics, chat, remarketing) should be deferred. - Delay non-essential third-party scripts. Load chat widgets, social embeds, and marketing pixels only after user interaction or after the page is fully loaded. WP Rocket’s “Delay JavaScript Execution” feature handles this.
- Optimize font loading. Use
font-display: swapso text renders immediately with a fallback font while the custom font downloads. Preload your most critical font file.
How to check: PageSpeed Insights lists every render-blocking resource under its “Eliminate render-blocking resources” diagnostic. DevTools’ Coverage tab shows how much of your CSS and JavaScript is actually used on the page.
Cause 3: Slow Resource Load Times
Even after the server responds quickly and rendering isn’t blocked, the LCP element itself might take too long to download. This is especially common with hero images.
Why it happens:
- Images served in unoptimized formats (PNG where JPEG would do, JPEG where WebP or AVIF would be better)
- Images not properly sized (serving a 3000px-wide image when the viewport only needs 1200px)
- No image compression
- Images loaded lazily when they shouldn’t be (more on this below)
- LCP image not discovered by the browser until late in the loading process
Fixes:
- Serve modern image formats. WebP offers 25-35% smaller file sizes than JPEG at equivalent quality. AVIF is even better. Use
<picture>elements with WebP/AVIF sources and a JPEG fallback, or let a CDN like Cloudflare handle automatic format conversion. - Properly size images. Serve responsive images using
srcsetandsizesattributes. A mobile user on a 400px-wide screen shouldn’t download a 2400px-wide image. - Compress images. Run images through ShortPixel, Imagify, or squoosh.app. Target quality around 80-85%: the file size difference is dramatic with virtually no visible quality loss.
- Never lazy-load the LCP image. This is one of the most common mistakes we see. Lazy loading defers image download until the element is near the viewport. Your LCP image is already in the viewport on page load. Lazy loading it only adds delay. Use
loading="eager"(or simply omit the loading attribute) for your hero image. - Preload the LCP image. Add a
<link rel="preload">tag in the<head>to tell the browser to start downloading the LCP image immediately, before it even parses the HTML that references it.
<link rel="preload" as="image" href="/images/hero.webp" type="image/webp">- Avoid CSS background images for LCP. The browser can’t discover a CSS background image until it has downloaded and parsed the CSS file. Use an HTML
<img>tag instead. The browser’s preload scanner finds<img>tags while parsing HTML, much earlier in the process.
Cause 4: Client-Side Rendering
Single-page applications (React, Vue, Angular) that render content entirely on the client add a significant delay. The browser has to download JavaScript, parse it, execute it, fetch data from an API, and then render the content. LCP suffers because the largest content element doesn’t exist until all that JavaScript runs.
Why it happens:
- JavaScript frameworks rendering content that could be server-rendered
- API calls required before content can be displayed
- Large JavaScript bundles that take seconds to download and parse
Fixes:
- Server-side rendering (SSR). Frameworks like Next.js (React) and Nuxt (Vue) render the initial HTML on the server, so content is visible before JavaScript executes. This is the most impactful fix for client-rendered sites.
- Static generation. For content that doesn’t change on every request, generate the HTML at build time. Astro, Next.js, and Nuxt all support static site generation. The resulting HTML is served from a CDN with zero server processing.
- Streaming SSR. Modern frameworks support streaming, where the server sends HTML in chunks as it’s generated. The browser can start rendering before the entire response is complete, improving LCP.
- Reduce JavaScript bundle size. Code-split so users only download the JavaScript needed for the current page. Tree-shake unused code. Lazy-load components below the fold.
Preloading LCP Resources: The Quick Win
If you make only one change from this article, preload your LCP resource. It’s the simplest fix with the most consistent impact.
For images:
<link rel="preload" as="image" href="/hero.webp" type="image/webp"
imagesrcset="/hero-400.webp 400w, /hero-800.webp 800w, /hero-1200.webp 1200w"
imagesizes="100vw">For fonts (if text is your LCP element):
<link rel="preload" as="font" href="/fonts/heading.woff2" type="font/woff2" crossorigin>The fetchpriority="high" attribute on LCP <img> elements is another powerful signal:
<img src="/hero.webp" fetchpriority="high" alt="...">This tells the browser to prioritize downloading this image over other resources. It’s supported in all modern browsers and consistently reduces LCP by 100-400 milliseconds in our testing.
Optimizing Images Specifically for LCP
Since hero images are the most common LCP element, here’s our standard optimization checklist:
srcset with at least 3 sizes (mobile, tablet, desktop)loading="eager" or no loading attribute (never loading="lazy")fetchpriority="high"<link rel="preload"> in the document head<img> tag to prevent layout shift<img> tag for discoverabilityMeasuring and Monitoring LCP
Lab Testing
- Google PageSpeed Insights: Tests from Google’s infrastructure, provides both lab data and field data (if available)
- Chrome DevTools Performance panel: Records and shows the LCP moment in the timeline
- WebPageTest: Advanced testing with waterfall charts showing exactly when and how your LCP element loads
- Lighthouse: Built into Chrome DevTools, provides an LCP score and diagnostics
Field Data (Real Users)
- Google Search Console Core Web Vitals report: Shows your site-wide LCP performance from real Chrome users
- Chrome User Experience Report (CrUX): The data behind Search Console’s report, accessible via API or BigQuery
- Web Vitals JavaScript library: Add to your site to send real-user LCP data to your analytics platform
Lab data is useful for testing fixes. Field data is what Google uses for rankings. Optimize until your field data is green.
Target Scores
The Fix Priority Order
When we tackle LCP for a client, this is our typical order of operations:
- Identify the LCP element: You can’t fix what you haven’t identified
- Check TTFB: If the server is slow, fix that first (caching, hosting, CDN)
- Preload the LCP resource: Fastest single fix
- Optimize the LCP image: Right format, right size, right compression
- Remove render-blocking resources: Inline critical CSS, defer JS
- Ensure no lazy loading on LCP: Common mistake, easy fix
- Add fetchpriority=”high”: Simple attribute, measurable impact
- Address client-side rendering: If applicable, most complex fix
Most sites see their LCP drop into the green zone after steps 1-5. Steps 6-8 push it from acceptable to excellent.
Keep Reading
- How Competitor Analysis Drives Smarter Local SEO Strategy
- When to Build a Progressive Web App (PWA) Instead of a Native App
- Cumulative Layout Shift: What It Is and How to Eliminate It
We sweat these milliseconds on every project. See the hand-coded rebuild we shipped for Hot Dog Business Growth in the case study.