How to Fix Core Web Vitals: LCP, CLS, and INP Troubleshooting Guide
Posted on June 29, 2026
Last updated: June 29, 2026 · 12 min read
If your Core Web Vitals are failing, you're losing rankings. Since June 2021, Google has confirmed that LCP, CLS, and INP are ranking signals—and in 2026, with the Page Experience Update v2, sites that fail CWV thresholds lose rankings even when their content is superior. The good news: most Core Web Vitals issues have predictable causes and proven fixes. This guide walks you through diagnosing and fixing all three metrics, with code snippets, plugin recommendations, and real before/after results from sites we've audited at Scanly.
Table of Contents
- 1. What Are Core Web Vitals in 2026?
- 2. How to Test Your Core Web Vitals
- 3. How to Fix LCP (Largest Contentful Paint)
- 4. How to Fix CLS (Cumulative Layout Shift)
- 5. How to Fix INP (Interaction to Next Paint)
- 6. WordPress-Specific Core Web Vitals Fixes
- 7. Core Web Vitals for E-commerce Sites
- 8. When to Stop Optimizing
- 9. FAQ: Core Web Vitals Fixes
What Are Core Web Vitals in 2026?
Core Web Vitals are three metrics Google uses to measure real-world user experience. They're calculated from CrUX (Chrome User Experience Report) data—actual data from real Chrome users, not lab simulations.
| Metric | What It Measures | Good | Needs Improvement | Poor |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | Loading performance of largest visible element | < 2.5s | 2.5–4.0s | > 4.0s |
| CLS (Cumulative Layout Shift) | Visual stability during load | < 0.1 | 0.1–0.25 | > 0.25 |
| INP (Interaction to Next Paint) | Responsiveness to user input | < 200ms | 200–500ms | > 500ms |
Important: INP replaced FID (First Input Delay) as a Core Web Vital in March 2024. FID measured only the first interaction; INP measures all interactions throughout the page session, making it a much stricter metric.
To pass Core Web Vitals, all three metrics must be in the "Good" range on mobile for at least 75% of page loads. Desktop performance matters for user experience but isn't currently a ranking factor.
How to Test Your Core Web Vitals
You have three options:
Option 1: PageSpeed Insights (Best for Single URL)
Go to PageSpeed Insights, enter your URL, and click Analyze. You'll get:
- Field data from CrUX (real Chrome users over last 28 days)
- Lab data from Lighthouse (simulated)
- Specific recommendations with estimated savings
This is the most accurate source for field data—Google uses this exact data for rankings.
Option 2: Google Search Console (Best for Site-Wide View)
In Search Console, open the Core Web Vitals report. It shows:
- How many URLs are "Poor", "Need Improvement", and "Good"
- Which URL groups are failing
- Which metric is failing for each group
This is the best way to identify which pages need attention.
Option 3: Scanly (Best for All-in-One Audit)
Scanly tests all three Core Web Vitals plus 100+ other SEO, accessibility, and security checks in a single 60-second scan. It also includes AI-generated fix recommendations.
How to Fix LCP (Largest Contentful Paint)
LCP measures when the largest visible element finishes rendering. For most pages, this is a hero image, hero video, or large text block. The target is under 2.5 seconds on mobile.
Diagnose LCP Issues
In PageSpeed Insights, find the "Largest Contentful Element" line in the Diagnostics section. It tells you exactly which element is the LCP and its current load time.
Common LCP elements:
- Hero images (45% of cases)
- Hero background images (20%)
- Large text blocks (15%)
- Video posters (10%)
- Logos or banners (10%)
LCP Fix #1: Optimize the LCP Image
If your LCP is an image, these fixes apply in priority order:
1a. Compress and convert to WebP/AVIF
# Convert to WebP at 80% quality (good balance) cjpeg --quality 80 input.jpg > output.webp # Or use Squoosh (free online tool) # https://squoosh.appTarget file size: under 100KB for hero images, under 50KB for above-the-fold images.
1b. Add fetchpriority="high" to the LCP image
<img src="hero.webp"
alt="Hero image"
fetchpriority="high"
width="1600"
height="900">This tells the browser to prioritize loading this image. Browsers don't always guess correctly which image is most important.
1c. Preload the LCP image
<link rel="preload"
as="image"
href="hero.webp"
fetchpriority="high">This starts loading the image before the HTML parser reaches the <img> tag.
1d. Stop lazy-loading the LCP image
Lazy-loading the LCP image is a common mistake. The LCP image should never have loading="lazy". WordPress 5.5+ adds lazy-loading by default to all images; you may need a plugin like Perfmatters or WP Rocket to disable it on the LCP image.
LCP Fix #2: Reduce Server Response Time (TTFB)
If your server takes 600ms+ to respond, even a perfect LCP image won't save you. Target TTFB under 600ms.
Diagnose: In PageSpeed Insights, find "Server Backend" or "Reduce initial server response time".
Common fixes:
- Upgrade hosting: Shared hosting often has TTFB 800ms+. Cloudways, Kinsta, WP Engine typically deliver 200–400ms.
- Use a CDN: Cloudflare (free) or BunnyCDN ($1/month) cache static assets at the edge.
- Enable page caching: WP Rocket, W3 Total Cache, or LiteSpeed Cache.
- Use object caching: Redis or Memcached for dynamic content.
- Optimize database: Add indexes, clean up transients, remove unused plugins.
LCP Fix #3: Eliminate Render-Blocking Resources
CSS and JavaScript in the <head> block rendering. Fix with:
<!-- Defer non-critical JavaScript -->
<script src="script.js" defer></script>
<!-- Async load non-critical JavaScript -->
<script src="analytics.js" async></script>
<!-- Inline critical CSS -->
<style>
/* Above-the-fold CSS only */
</style>
<!-- Preload remaining CSS -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">For WordPress, use Autoptimize or WP Rocket to automatically inline critical CSS and defer non-critical JS.
LCP Fix #4: Avoid Client-Side Rendering for Above-the-Fold Content
If your site uses React, Vue, or another client-side framework, the browser downloads an empty HTML file and renders content with JavaScript. This destroys LCP.
Solutions:
- Server-side rendering (SSR): Next.js, Nuxt.js, or SvelteKit
- Static site generation (SSG): Pre-render pages at build time
- Hydration: Render HTML on server, hydrate on client
- Skeleton screens: Show static content immediately, hydrate later
LCP Fix #5: Reduce Third-Party Script Impact
Third-party scripts (analytics, chat widgets, ads, social embeds) can block the main thread and delay LCP.
Quick wins:
- Delay analytics until after user interaction (Partytown, Plausible)
- Self-host fonts instead of loading from Google Fonts
- Replace chat widgets with delayed-load versions (Crisp, Intercom)
- Use lazy-loading for embeds (Tweets, YouTube, Instagram)
How to Fix CLS (Cumulative Layout Shift)
CLS measures visual stability. Every time an element moves after the page has rendered, you accumulate CLS. Target under 0.1.
Diagnose CLS Issues
In PageSpeed Insights, find "Avoid large layout shifts" in Diagnostics. It lists elements that shifted and their contribution to CLS.
Common CLS culprits:
- Images without dimensions (40% of cases)
- Web fonts causing FOUT/FOIT (25%)
- Dynamically injected content like ads and banners (20%)
- Slow-loading embeds (10%)
- Async CSS/HTML injections (5%)
CLS Fix #1: Always Specify Image Dimensions
The #1 cause of CLS is images without width and height attributes. The browser doesn't know how much space to reserve, so when the image loads, content shifts.
<!-- BAD -->
<img src="photo.jpg" alt="Photo">
<!-- GOOD -->
<img src="photo.jpg" alt="Photo" width="800" height="600">For responsive images, use aspect-ratio in CSS:
img {
aspect-ratio: 4 / 3;
width: 100%;
height: auto;
}WordPress 5.5+ adds dimensions automatically, but custom themes and page builders often miss them.
CLS Fix #2: Reserve Space for Ads and Embeds
If you display ads or embeds, reserve space before they load using CSS:
.ad-slot {
min-height: 250px;
width: 100%;
}
.twitter-embed {
min-height: 200px;
}For ads that vary in size, use the largest expected size as min-height.
CLS Fix #3: Preload Web Fonts
Web fonts cause layout shift when the fallback font is replaced by the web font (FOUT—Flash of Unstyled Text) or when text is invisible until the font loads (FOIT—Flash of Invisible Text).
Solutions:
<!-- Preload fonts -->
<link rel="preload"
as="font"
href="/fonts/inter.woff2"
type="font/woff2"
crossorigin>
<!-- Use font-display: swap -->
<style>
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
}
</style>For Google Fonts, add &display=swap to the URL:
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">Better yet, self-host your fonts. This eliminates the DNS lookup and TLS handshake to fonts.googleapis.com.
CLS Fix #4: Avoid Dynamically Injected Content Above Existing Content
Banner notifications, cookie banners, and chat widgets that push content down cause CLS. Fix by:
- Reserve space for them in the layout
- Use
position: fixedorposition: absoluteto overlay instead of push - Use CSS transforms (
transform: translateY()) for animations
CLS Fix #5: Use CSS Containment
For complex layouts, CSS containment tells the browser that an element's contents don't affect the rest of the page:
.widget {
contain: layout style paint;
}This prevents the widget from causing layout shifts elsewhere on the page.
How to Fix INP (Interaction to Next Paint)
INP measures how quickly your page responds to user input (clicks, taps, keypresses). It's the newest Core Web Vital and the one most sites fail. Target under 200ms.
Diagnose INP Issues
INP issues are harder to diagnose because they require real user interaction. Tools:
- PageSpeed Insights: Shows INP in field data
- Chrome DevTools Performance tab: Record interaction and look for long tasks
- web-vitals JavaScript library: Add to your site to collect real INP data from visitors
import {onINP} from 'web-vitals';
onINP((metric) => {
console.log('INP:', metric.value);
// Send to analytics
navigator.sendBeacon('/analytics', JSON.stringify({
type: 'INP',
value: metric.value,
path: location.pathname
}));
});INP Fix #1: Break Up Long Tasks
JavaScript that runs for more than 50ms blocks the main thread and delays interactions. Use requestIdleCallback or setTimeout to break up long tasks:
// BAD - blocks main thread for 200ms
function processLargeArray(items) {
items.forEach(item => {
heavyComputation(item);
});
}
// GOOD - yields to main thread
function processLargeArray(items) {
function processChunk(start) {
const end = Math.min(start + 50, items.length);
for (let i = start; i < end; i++) {
heavyComputation(items[i]);
}
if (end < items.length) {
// Yield to main thread
setTimeout(() => processChunk(end), 0);
}
}
processChunk(0);
}Or use the newer scheduler.yield() API (Chrome 129+):
async function processLargeArray(items) {
for (let i = 0; i < items.length; i++) {
heavyComputation(items[i]);
if (i % 50 === 0) {
await scheduler.yield();
}
}
}INP Fix #2: Optimize Event Handlers
Inefficient event handlers are a major cause of INP issues.
Debounce input handlers:
// BAD - runs on every keystroke
input.addEventListener('input', (e) => {
searchDatabase(e.target.value);
});
// GOOD - debounced
function debounce(fn, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => fn.apply(this, args), delay);
};
}
input.addEventListener('input', debounce((e) => {
searchDatabase(e.target.value);
}, 250));Use event delegation instead of attaching handlers to many elements:
// BAD - 1000 handlers
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', handleClick);
});
// GOOD - 1 handler
document.addEventListener('click', (e) => {
if (e.target.closest('.item')) {
handleClick(e);
}
});INP Fix #3: Reduce Third-Party JavaScript
Third-party scripts (analytics, chat widgets, ads, A/B testing) often run on the main thread and block interactions.
Solutions:
- Use Partytown to run third-party scripts in a Web Worker
- Replace heavy analytics (Google Analytics 4) with lightweight alternatives (Plausible, Fathom, Umami)
- Delay chat widgets until after first interaction
- Use server-side tagging (GTM Server-Side)
INP Fix #4: Optimize Click Targets
For interactive elements like buttons and links, ensure they respond immediately:
// BAD - waits for backend
button.addEventListener('click', async () => {
const result = await fetch('/api');
updateUI(result);
});
// GOOD - optimistic UI
button.addEventListener('click', async () => {
updateUI(expectedResult); // Update immediately
const result = await fetch('/api');
updateUI(result); // Correct if needed
});INP Fix #5: Use Content-Visibility for Long Lists
If you have long lists or feeds, use content-visibility: auto to skip rendering off-screen content:
.feed-item {
content-visibility: auto;
contain-intrinsic-size: 200px;
}This dramatically reduces INP on long pages.
WordPress-Specific Core Web Vitals Fixes
WordPress sites have specific CWV patterns. Here's the priority order for WordPress:
WordPress Fix #1: Install a Caching Plugin (5 minutes)
WP Rocket ($59/year) is the easiest. Free alternatives: LiteSpeed Cache (works on LiteSpeed servers only), W3 Total Cache (powerful but complex), WP Super Cache (basic).
WordPress Fix #2: Optimize Images (15 minutes)
Install ShortPixel, Imagify, or Smush. Configure to:
- Convert to WebP automatically
- Compress to 80% quality
- Lazy-load images (but exclude LCP image)
WordPress Fix #3: Disable Unused Plugins (10 minutes)
Each plugin adds JavaScript and CSS. Deactivate and delete anything you don't actively use.
WordPress Fix #4: Use a Performance-Focused Theme
Astra, GeneratePress, and Kadence are lightweight themes that score well on CWV out of the box. Avoid multipurpose themes like Avada, Divi, and Jupiter X—they bundle hundreds of KB of unused code.
WordPress Fix #5: Replace Heavy Page Builders
Elementor, Divi Builder, and WPBakery add significant JavaScript payload. Where possible, use the Gutenberg block editor or lightweight builders like Bricks or Spectra.
Core Web Vitals for E-commerce Sites
E-commerce sites face unique CWV challenges:
Product Image Galleries
Product pages often have 5–10 images. Without optimization, these destroy LCP and INP.
Solutions:
- Use
srcsetfor responsive images - Compress to WebP at 75% quality
- Lazy-load non-primary images
- Use thumbnails in gallery, full-size on click
Cart and Checkout Interactions
Cart updates and form submissions are common INP killers.
Solutions:
- Use optimistic UI for cart updates
- Debounce quantity inputs
- Use Web Workers for price calculations
- Prefetch checkout page resources
Third-Party Scripts (Analytics, Pixel, Chat)
E-commerce sites typically have 10+ third-party scripts.
Solutions:
- Audit scripts with Chrome DevTools Coverage tab
- Remove duplicate analytics (e.g., GA4 + GTM + Universal Analytics)
- Use server-side tagging
- Delay non-critical scripts until after first interaction
When to Stop Optimizing
Core Web Vitals have diminishing returns. Once all three metrics are "Good", additional optimization rarely improves rankings. Stop and move on to content and links.
Stop optimizing when:
- LCP < 2.5s on mobile for 75%+ of page loads (CrUX data)
- CLS < 0.1 on mobile for 75%+ of page loads
- INP < 200ms on mobile for 75%+ of page loads
- Search Console Core Web Vitals report shows green
Don't optimize further when:
- Lab data (Lighthouse) shows issues but field data is good
- You're optimizing for desktop (not a ranking factor)
- Your competitors' CWV is worse than yours
Test Your Core Web Vitals Free
Run a free 60-second audit with Scanly to test your LCP, CLS, and INP plus 100+ other SEO, accessibility, and security checks. Get AI-generated fix recommendations specific to your site.
Try Scanly Free — No Credit Card RequiredFAQ: Core Web Vitals Fixes
How long does it take to fix Core Web Vitals?
For a typical WordPress site, expect 4–8 hours of work to fix all three metrics. Simple fixes (image dimensions, fetchpriority) take 30 minutes. Complex fixes (server migration, framework change) take weeks.
Why is my LCP still high after optimizing the image?
Check for these additional causes: slow server (TTFB > 600ms), render-blocking CSS/JS, client-side rendering, third-party scripts, or no CDN. Use PageSpeed Insights "Eliminate render-blocking resources" and "Reduce server response time" diagnostics.
What's a good CLS score?
Under 0.1 is "Good". 0.1–0.25 "Needs Improvement". Above 0.25 is "Poor". For most sites, achieving 0.05 or lower is realistic with proper image dimensions, font preloading, and reserved space for ads.
Why did my INP suddenly get worse?
INP can worsen after adding a new third-party script, a plugin update, or a theme change. Check your most recent site changes and use the web-vitals library to identify which pages have poor INP.
Do Core Web Vitals affect desktop rankings?
Google uses mobile-first indexing, so mobile CWV is the ranking factor. Desktop CWV matters for user experience but isn't a direct ranking signal. However, if your desktop CWV is much better than mobile, you have a mobile-specific issue to fix.
Can I pass Core Web Vitals with a heavy plugin like Elementor?
Yes, but it requires aggressive optimization: WP Rocket or similar, image optimization, unused CSS removal, and selective asset unloading. Sites with Elementor can pass CWV, but they require more maintenance than lightweight Gutenberg sites.
How often does Google update Core Web Vitals data?
CrUX data updates monthly. Search Console Core Web Vitals report updates every 2–4 weeks. PageSpeed Insights field data reflects the last 28 days. After making fixes, expect 4–6 weeks for ranking impact.
Should I use Lighthouse or PageSpeed Insights?
Use both. Lighthouse gives you lab data (immediate feedback during development). PageSpeed Insights gives you field data (what real users experience). Field data is what Google uses for rankings, so prioritize it.
Related Reading
- Technical SEO Audit: The Complete 2026 Guide
- AI Tools for Website Performance Analysis
- Website Page Speed Optimization
- How to Run a Website Performance Audit in 2026
- Free SEO Audit Tool: Check Your Website Score Online
Ready to fix your Core Web Vitals? Try Scanly completely free and get a comprehensive audit with AI-generated fix recommendations in under 60 seconds. No credit card required.
Lead SEO Analyst at Scanly
Sarah Chen is the lead SEO analyst at Scanly, where she has audited over 10,000 websites. She specializes in technical SEO, Core Web Vitals optimization, and AI search strategy.