Core Web Vitals Optimization Guide
Learn how to measure, understand, and improve your Core Web Vitals scores for better user experience and search rankings.
Last updated November 15, 2024
Core Web Vitals are a set of specific factors that Google considers important for a webpage's overall user experience. As confirmed ranking signals, optimizing these metrics is essential for SEO success.
Understanding the Three Core Web Vitals
Largest Contentful Paint (LCP)
What it measures: Loading performance—how quickly the main content loads.
Target: Under 2.5 seconds
What counts as LCP:
- Images (including background images)
- Video poster images
- Block-level text elements
- Elements with background images loaded via
url()
Common causes of poor LCP:
- Slow server response times
- Render-blocking JavaScript and CSS
- Slow resource load times
- Client-side rendering delays
First Input Delay (FID)
What it measures: Interactivity—how quickly users can interact with your page.
Target: Under 100 milliseconds
What triggers FID measurement:
- Clicks
- Taps
- Key presses
Note: FID is being replaced by Interaction to Next Paint (INP) in March 2024
Common causes of poor FID:
- Long JavaScript tasks
- Heavy JavaScript execution
- Large bundle sizes
- Third-party script impact
Cumulative Layout Shift (CLS)
What it measures: Visual stability—how much the page layout shifts during loading.
Target: Under 0.1
What causes layout shifts:
- Images without dimensions
- Ads, embeds, and iframes without dimensions
- Dynamically injected content
- Web fonts causing FOIT/FOUT
Measuring Core Web Vitals
Lab Data Tools
For development and testing:
- Lighthouse (Chrome DevTools)
- PageSpeed Insights
- WebPageTest
Field Data Tools
Real user data:
- Chrome User Experience Report (CrUX)
- Google Search Console
- Web Vitals JavaScript library
Setting Up Monitoring
Add the Web Vitals library to track real users:
import {onLCP, onFID, onCLS} from 'web-vitals';
onLCP(console.log);
onFID(console.log);
onCLS(console.log);
Optimizing LCP
1. Optimize Server Response Time
- Use a CDN
- Cache pages where possible
- Establish early third-party connections with
preconnect
<link rel="preconnect" href="https://cdn.example.com">
2. Eliminate Render-Blocking Resources
Move non-critical CSS and JavaScript:
<!-- Defer non-critical JS -->
<script defer src="non-critical.js"></script>
<!-- Async for independent scripts -->
<script async src="analytics.js"></script>
3. Optimize Images
- Use modern formats (WebP, AVIF)
- Serve appropriately sized images
- Implement lazy loading for below-fold images
<img
src="image.webp"
loading="lazy"
width="800"
height="600"
alt="Description"
>
4. Preload Critical Resources
<link rel="preload" href="hero-image.webp" as="image">
<link rel="preload" href="critical-font.woff2" as="font" crossorigin>
Optimizing FID/INP
1. Break Up Long Tasks
Split JavaScript into smaller chunks:
// Instead of one long task
function processAll() {
// 500ms of work
}
// Break into smaller tasks
function processChunk() {
// 50ms of work
setTimeout(processNextChunk, 0);
}
2. Use Web Workers
Offload heavy computation:
const worker = new Worker('heavy-computation.js');
worker.postMessage(data);
worker.onmessage = (e) => handleResult(e.data);
3. Reduce JavaScript
- Remove unused code
- Code-split by route
- Lazy load below-fold components
4. Optimize Third-Party Scripts
- Audit all third-party scripts
- Load non-critical scripts after page load
- Consider self-hosting critical third-party resources
Optimizing CLS
1. Always Include Size Attributes
<!-- Always specify dimensions -->
<img src="image.jpg" width="800" height="600" alt="...">
<!-- Or use aspect-ratio in CSS -->
<style>
.image-container {
aspect-ratio: 16 / 9;
}
</style>
2. Reserve Space for Dynamic Content
/* Reserve space for ads */
.ad-container {
min-height: 250px;
}
3. Avoid Inserting Content Above Existing Content
If you must add content dynamically:
- Add it below the viewport
- Use transforms instead of changing layout properties
- Reserve space with placeholders
4. Optimize Web Fonts
/* Prevent FOUT/FOIT */
@font-face {
font-family: 'CustomFont';
font-display: optional; /* or 'swap' */
src: url('font.woff2') format('woff2');
}
Consider using font-display: optional for non-critical fonts.
Priority Action Matrix
| Issue | Impact | Difficulty | Priority |
|---|---|---|---|
| Unoptimized images | LCP | Easy | High |
| Render-blocking CSS | LCP | Medium | High |
| Long JavaScript tasks | FID | Medium | High |
| Images without dimensions | CLS | Easy | High |
| Web font flash | CLS | Easy | Medium |
| Third-party scripts | FID | Hard | Medium |
| Dynamic content injection | CLS | Medium | Medium |
Testing Your Improvements
Before & After Process
- Baseline: Run PageSpeed Insights on key pages
- Document: Save scores for LCP, FID/INP, CLS
- Implement: Make one change at a time
- Measure: Re-test after each change
- Monitor: Watch field data over 28 days
Key Pages to Test
- Homepage
- Top landing pages
- Product/service pages
- Blog posts
- Category/listing pages
Common Pitfalls
Don't Over-Optimize
Some optimization attempts backfire:
- Lazy loading above-fold images (hurts LCP)
- Too much critical CSS (delays first byte)
- Over-splitting JavaScript (waterfall requests)
Remember Field vs. Lab Data
- Lab data shows potential issues
- Field data shows real user experience
- Google uses field data (CrUX) for rankings
Conclusion
Core Web Vitals optimization is iterative:
- Measure current performance
- Identify biggest opportunities
- Implement fixes one at a time
- Monitor impact in field data
- Repeat
Focus on the changes that will have the biggest impact on real users, and the ranking benefits will follow.
Put these strategies into action
Use SECrawl to audit your website and implement these recommendations.
Start Free