Core Web Vitals Guide: Improve Performance and Rankings
Core Web Vitals are Google’s metrics for measuring user experience. Since 2021, they’ve been a confirmed ranking factor. Sites that pass Core Web Vitals thresholds have measurably lower bounce rates and better engagement.
This guide explains each metric, how to measure them, and specific techniques to improve your scores. Whether you’re a developer optimizing a complex app or a non-technical founder trying to understand what’s slowing down your site, you’ll find actionable guidance here.
What Are Core Web Vitals?
Core Web Vitals are three specific metrics that measure loading performance, interactivity, and visual stability:
| Metric | Measures | Good | Needs Improvement | Poor |
|---|---|---|---|---|
| LCP | Loading | ≤2.5s | 2.5-4s | >4s |
| INP | Interactivity | ≤200ms | 200-500ms | >500ms |
| CLS | Visual Stability | ≤0.1 | 0.1-0.25 | >0.25 |
Why Core Web Vitals Matter
Ranking factor: Google uses Core Web Vitals as part of its page experience signals. While content relevance still dominates rankings, CWV can be a tiebreaker between similar pages.
User experience: These metrics correlate with real user behavior. Poor LCP means users wait frustratingly long for content. Poor INP means clicks feel sluggish. Poor CLS means users accidentally click the wrong thing when layouts shift.
Business impact: Studies show sites passing CWV thresholds see 24% lower abandonment rates. Faster, more stable pages convert better.
Understanding Each Metric
LCP (Largest Contentful Paint)
LCP measures how long it takes for the largest visible content element to render. This is typically:
- A hero image
- A background image
- A large block of text
- A video poster image
Users perceive a page as “loaded” when the main content appears. LCP captures this perception.
Thresholds:
- Good: ≤2.5 seconds
- Needs Improvement: 2.5-4 seconds
- Poor: >4 seconds
INP (Interaction to Next Paint)
INP measures how quickly the page responds to user interactions. It replaced First Input Delay (FID) in 2024 as a more comprehensive metric.
Unlike FID (which measured only the first interaction), INP considers all interactions throughout the page lifecycle and reports the worst-case latency (with outliers removed).
An interaction includes:
- Clicking a button or link
- Typing in a field
- Tapping on mobile
The measurement captures the time from interaction to when the visual response appears.
Thresholds:
- Good: ≤200 milliseconds
- Needs Improvement: 200-500 milliseconds
- Poor: >500 milliseconds
CLS (Cumulative Layout Shift)
CLS measures unexpected layout movement. When elements shift after rendering, users may click the wrong thing or lose their reading position.
Common causes of layout shifts:
- Images without explicit dimensions
- Ads loading after page content
- Web fonts causing text reflow
- Dynamic content injected above existing content
CLS is unitless—it’s a score calculated from the size and distance of shifting elements.
Thresholds:
- Good: ≤0.1
- Needs Improvement: 0.1-0.25
- Poor: >0.25
Measuring Core Web Vitals
Field Data vs Lab Data
Field data comes from real users visiting your site. This is what Google uses for ranking signals. You’ll find it in:
- Google Search Console (Core Web Vitals report)
- PageSpeed Insights (top section, if available)
- Chrome User Experience Report (CrUX)
- Real User Monitoring (RUM) tools
Lab data comes from simulated tests in controlled environments. Useful for debugging but not what Google uses for rankings. Sources include:
- Lighthouse (in Chrome DevTools)
- PageSpeed Insights (lab data section)
- WebPageTest
Focus on field data for understanding your ranking impact. Use lab data for debugging and development.
Using PageSpeed Insights
- Enter your URL at pagespeed.web.dev
- Review field data section first (if available)
- Check the “Core Web Vitals Assessment”
- Scroll to lab data for detailed diagnostics
- Review the “Opportunities” and “Diagnostics” sections
If field data isn’t available, your page doesn’t have enough traffic in the Chrome User Experience Report. Focus on lab data and building traffic.
Google Search Console
GSC shows field data grouped by status (Good, Needs Improvement, Poor) for both mobile and desktop. URLs are grouped by similar issues, making it easier to prioritize fixes.
Check GSC weekly to monitor trends and catch regressions.
LCP Optimization
LCP is often the most impactful metric to improve. Here are the key optimization strategies:
Optimize the LCP Element
First, identify your LCP element. In Chrome DevTools:
- Open DevTools (F12)
- Go to Performance tab
- Record a page load
- Look for the “LCP” marker
- Click it to see which element it refers to
Image Optimization
If your LCP element is an image:
Use modern formats:
<picture>
<source srcset="hero.avif" type="image/avif">
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Hero image" width="1200" height="600">
</picture>
Size images properly: Don’t serve a 4000px image for a 400px display. Resize to match layout size.
Preload the LCP image:
<link rel="preload" as="image" href="/hero.webp">
Set high fetch priority:
<img src="/hero.webp" fetchpriority="high" alt="Hero">
Don’t lazy load the LCP element: Lazy loading delays loading. Only lazy load images below the fold.
Reduce Server Response Time
TTFB (Time to First Byte) affects LCP. If your server is slow, everything is slow.
- Use a CDN: Serve content from edge locations near users
- Optimize database queries: Slow queries delay the entire page
- Use caching: Reduce computation on repeated requests
- Upgrade hosting: Cheap shared hosting is often slow
Target TTFB under 200ms.
Eliminate Render-Blocking Resources
CSS and JavaScript in the <head> can block rendering.
Inline critical CSS: Put styles needed for above-fold content directly in <style> tags.
Defer non-critical JavaScript:
<script defer src="/app.js"></script>
Load third-party scripts asynchronously:
<script async src="https://analytics.example.com/script.js"></script>
Preconnect to Origins
If you load resources from other domains, preconnect to save connection time:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com">
INP Optimization
INP problems usually stem from JavaScript blocking the main thread. The browser can’t respond to user input while executing JavaScript.
Identify Long Tasks
In Chrome DevTools Performance tab, look for tasks over 50ms (marked in red). These “long tasks” block user interaction.
Break Up Long Tasks
Instead of running expensive operations in one block, yield to the main thread periodically:
// Bad: Blocks for entire duration
function processData(items) {
items.forEach(item => expensiveOperation(item));
}
// Better: Yields to main thread
async function processData(items) {
for (const item of items) {
expensiveOperation(item);
// Yield to allow user interactions
await new Promise(resolve => setTimeout(resolve, 0));
}
}
Modern browsers support scheduler.yield() for more efficient yielding.
Reduce JavaScript
Less JavaScript means fewer blocking opportunities.
- Remove unused code: Audit your bundles for dead code
- Code splitting: Load only what’s needed for each page
- Tree shaking: Let bundlers eliminate unused exports
- Lazy load non-critical features: Load below-fold or secondary features on demand
Optimize Event Handlers
- Debounce or throttle handlers for scroll/resize events
- Move expensive computation out of handlers
- Use passive event listeners for scroll:
element.addEventListener('scroll', handler, { passive: true });
Audit Third-Party Scripts
Analytics, chat widgets, and other third-party scripts often cause INP issues. Audit what’s loaded and whether it’s worth the performance cost.
Consider:
- Lazy loading third-party scripts
- Using lighter alternatives
- Removing unused integrations
CLS Optimization
CLS is often the easiest metric to fix because solutions are straightforward.
Always Set Image Dimensions
Never let images render without specified dimensions:
<!-- Always include width and height -->
<img src="photo.jpg" width="800" height="600" alt="Description">
<!-- Or use aspect-ratio in CSS -->
<img src="photo.jpg" style="aspect-ratio: 4/3; width: 100%;" alt="Description">
This reserves space before the image loads, preventing layout shift.
Reserve Space for Dynamic Content
If content loads asynchronously (ads, embeds, lazy content), reserve space:
.ad-container {
min-height: 250px; /* Reserve space for ad */
}
.video-embed {
aspect-ratio: 16/9;
}
Optimize Web Fonts
Fonts loading after content can cause text reflow (Flash of Unstyled Text).
@font-face {
font-family: 'MyFont';
font-display: optional; /* Prevents layout shift */
src: url('/fonts/myfont.woff2') format('woff2');
}
Or use font-display: swap with size-adjust to minimize reflow:
@font-face {
font-family: 'MyFont';
font-display: swap;
size-adjust: 105%; /* Adjust to match fallback size */
src: url('/fonts/myfont.woff2') format('woff2');
}
Don’t Insert Content Above Existing Content
Adding content above the viewport pushes everything down, causing shift. If you must add content dynamically, add it below the fold or use transitions that don’t affect layout.
Use Transform for Animations
Animations using top, left, width, or height trigger layout. Use transform instead:
/* Bad: Causes layout */
.element {
animation: slide 0.3s;
}
@keyframes slide {
from { top: 0; }
to { top: 100px; }
}
/* Good: No layout shift */
.element {
animation: slide 0.3s;
}
@keyframes slide {
from { transform: translateY(0); }
to { transform: translateY(100px); }
}
Platform-Specific Fixes
WordPress
| Issue | Solution |
|---|---|
| Large images | Use image optimization plugin (ShortPixel, Imagify) |
| Slow hosting | Upgrade to quality managed WordPress hosting |
| Too many plugins | Audit and remove unused plugins |
| No caching | Install caching plugin (WP Rocket, W3 Total Cache) |
| Render-blocking | Use Autoptimize or WP Rocket |
Shopify
| Issue | Solution |
|---|---|
| Heavy themes | Choose performance-optimized theme |
| Too many apps | Remove unused apps |
| Large images | Optimize before uploading |
| Third-party scripts | Lazy load where possible |
Next.js / React
| Issue | Solution |
|---|---|
| Large bundle | Code splitting, dynamic imports |
| Hydration blocking | Suspense, progressive hydration |
| Images | Use next/image component |
| Third-party | Load analytics asynchronously |
Prioritization Framework
Not all fixes are equal. Prioritize by impact and effort:
High Impact, Low Effort (Do First)
- Image optimization (format, sizing, preload)
- Set dimensions on images/embeds
- CDN configuration
- Critical CSS inlining
High Impact, High Effort (Plan Carefully)
- Code splitting and lazy loading
- Third-party script optimization
- Platform migration
- Architecture changes
Low Impact, Low Effort (Quick Wins)
- Minor JavaScript cleanup
- Preconnect hints
- Cache header improvements
Low Impact, High Effort (Probably Skip)
- Custom font optimization beyond basics
- Edge-specific rendering
Recommended Order
- Identify worst pages: Use GSC to find pages failing CWV
- Fix LCP first: Usually has the biggest impact
- Address CLS: Often quick fixes (dimensions, reserved space)
- Tackle INP: Usually most complex, requiring code changes
Common Myths
Myth: A 100 Lighthouse score means perfect Core Web Vitals. Reality: Lighthouse is lab data. Real users may experience different performance. Field data is what matters for rankings.
Myth: Core Web Vitals is the most important ranking factor. Reality: Content relevance still dominates. CWV is one signal among many, often a tiebreaker between similar pages.
Myth: You need perfect scores. Reality: Passing the “Good” threshold is the goal. Improvements beyond that have diminishing returns for SEO purposes.
Myth: Lab scores match real-world performance. Reality: Real users have varying devices, networks, and conditions. Field data often differs significantly from lab tests.
Monitoring and Maintenance
Set Up Monitoring
- GSC: Check Core Web Vitals report weekly
- RUM tools: Consider SpeedCurve, DebugBear, or similar for detailed monitoring
- Alerts: Set up notifications for regressions
Prevent Regressions
- Performance budgets: Fail CI/CD if metrics regress
- Lighthouse CI: Automated testing on pull requests
- Regular audits: Monthly review of CWV status
Field Data Lag
Field data in Google Search Console and PageSpeed Insights represents a 28-day rolling average. After making improvements, wait 2-4 weeks to see the impact reflected in field data.
Checklist
Before Optimization
- Document current scores (field data)
- Identify worst-performing pages
- Identify LCP element for key pages
- Identify CLS sources
LCP Fixes
- Images optimized (modern format, proper sizing)
- LCP image preloaded
- Server response time under 200ms
- Critical CSS inlined
- Render-blocking resources eliminated
INP Fixes
- Long tasks identified and broken up
- Unused JavaScript removed
- Third-party scripts audited
- Event handlers optimized
CLS Fixes
- All images have explicit dimensions
- Web fonts optimized
- Space reserved for dynamic content
- No content injection above fold
After Optimization
- Lab data shows improvement
- Monitoring set up for regressions
- Wait for field data update (2-4 weeks)
Key Takeaways
Core Web Vitals matter for both rankings and user experience. The metrics aren’t arbitrary—they measure real aspects of how users experience your site.
Focus on:
- Field data over lab data for understanding ranking impact
- LCP first, then CLS, then INP (typical priority order)
- “Good” thresholds as the goal, not perfection
- Platform-appropriate solutions for your tech stack
- Monitoring to prevent regressions
Performance optimization is ongoing. Set up monitoring, establish baselines, and continuously improve. Your users—and your rankings—will benefit.