Web Vitals: Core Performance Metrics
Understanding and optimizing Core Web Vitals for better user experience and SEO
Web Vitals: Core Performance Metrics
Core Web Vitals are a set of metrics that measure real-world user experience on your website. These metrics are crucial for SEO, user satisfaction, and overall site performance.
What are Core Web Vitals?
Core Web Vitals are three specific metrics that Google considers essential for a good user experience:
- Largest Contentful Paint (LCP) - Loading performance
- First Input Delay (FID) - Interactivity
- Cumulative Layout Shift (CLS) - Visual stability
Largest Contentful Paint (LCP)
LCP measures loading performance by identifying when the largest content element becomes visible.
What is LCP?
LCP measures the time from when the page starts loading to when the largest text or image element is rendered.
Good vs Poor LCP
- Good: ≤ 2.5 seconds
- Needs Improvement: 2.5 - 4.0 seconds
- Poor: > 4.0 seconds
Common LCP Elements
<!-- Large images -->
<img src="hero-image.jpg" alt="Hero" />
<!-- Large text blocks -->
<h1>Main Heading</h1>
<!-- Background images -->
<div style="background-image: url('hero-bg.jpg')"></div>
<!-- Video elements -->
<video src="hero-video.mp4"></video>
Optimizing LCP
1. Optimize Images
<!-- Use modern formats -->
<picture>
<source srcset="hero.avif" type="image/avif">
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Hero" loading="eager" />
</picture>
<!-- Preload critical images -->
<link rel="preload" as="image" href="hero-image.jpg" />
<!-- Use appropriate sizes -->
<img
src="hero.jpg"
alt="Hero"
sizes="(max-width: 768px) 100vw, 50vw"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
/>
2. Optimize Server Response
// Server-side rendering
export async function getServerSideProps() {
const data = await fetchData();
return {
props: { data }
};
}
// Static generation
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
revalidate: 60 // ISR
};
}
3. Remove Render-Blocking Resources
<!-- Defer non-critical CSS -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<!-- Defer JavaScript -->
<script src="script.js" defer></script>
<!-- Inline critical CSS -->
<style>
/* Critical above-the-fold styles */
.hero { display: block; }
</style>
First Input Delay (FID)
FID measures interactivity by tracking the time between a user's first interaction and the browser's response.
What is FID?
FID measures the delay between when a user first interacts with your page (click, tap, key press) and when the browser can respond to that interaction.
Good vs Poor FID
- Good: ≤ 100 milliseconds
- Needs Improvement: 100 - 300 milliseconds
- Poor: > 300 milliseconds
Optimizing FID
1. Break Up Long Tasks
// ❌ Bad - Long task
function processLargeDataset(data) {
for (let i = 0; i < data.length; i++) {
// Heavy computation
processItem(data[i]);
}
}
// ✅ Good - Break up long tasks
function processLargeDataset(data) {
let index = 0;
function processChunk() {
const start = performance.now();
while (index < data.length && performance.now() - start < 5) {
processItem(data[index]);
index++;
}
if (index < data.length) {
setTimeout(processChunk, 0);
}
}
processChunk();
}
2. Use Web Workers
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: largeDataset });
worker.onmessage = function(e) {
const result = e.data;
updateUI(result);
};
// worker.js
self.onmessage = function(e) {
const { data } = e.data;
const result = processData(data);
self.postMessage(result);
};
3. Optimize JavaScript Execution
// ❌ Bad - Heavy computation on main thread
function calculateFibonacci(n) {
if (n <= 1) return n;
return calculateFibonacci(n - 1) + calculateFibonacci(n - 2);
}
// ✅ Good - Use memoization
const memo = new Map();
function calculateFibonacci(n) {
if (memo.has(n)) return memo.get(n);
const result = n <= 1 ? n :
calculateFibonacci(n - 1) + calculateFibonacci(n - 2);
memo.set(n, result);
return result;
}
Cumulative Layout Shift (CLS)
CLS measures visual stability by tracking unexpected layout shifts.
What is CLS?
CLS measures the sum of all individual layout shift scores for every unexpected layout shift that occurs during the page's lifetime.
Good vs Poor CLS
- Good: ≤ 0.1
- Needs Improvement: 0.1 - 0.25
- Poor: > 0.25
Common Causes of CLS
1. Images Without Dimensions
<!-- ❌ Bad - Causes layout shift -->
<img src="image.jpg" alt="Image" />
<!-- ✅ Good - Specify dimensions -->
<img src="image.jpg" alt="Image" width="400" height="300" />
<!-- Or use aspect ratio -->
<img src="image.jpg" alt="Image" style="aspect-ratio: 4/3;" />
2. Dynamic Content
<!-- ❌ Bad - Content loads after layout -->
<div id="content">
<!-- Content loads dynamically -->
</div>
<!-- ✅ Good - Reserve space -->
<div id="content" style="min-height: 200px;">
<!-- Content loads dynamically -->
</div>
3. Fonts Loading
/* ❌ Bad - Font swap causes layout shift */
@font-face {
font-family: 'Custom Font';
src: url('font.woff2');
font-display: swap;
}
/* ✅ Good - Use font-display: optional */
@font-face {
font-family: 'Custom Font';
src: url('font.woff2');
font-display: optional;
}
/* Or preload fonts */
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
Measuring Web Vitals
1. Chrome DevTools
// Measure LCP
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.startTime);
}).observe({ entryTypes: ['largest-contentful-paint'] });
// Measure FID
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
entries.forEach(entry => {
console.log('FID:', entry.processingStart - entry.startTime);
});
}).observe({ entryTypes: ['first-input'] });
// Measure CLS
let clsValue = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
console.log('CLS:', clsValue);
}).observe({ entryTypes: ['layout-shift'] });
2. Web Vitals Library
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getFCP(console.log);
getLCP(console.log);
getTTFB(console.log);
3. Real User Monitoring
// Send to analytics
function sendToAnalytics(metric) {
gtag('event', metric.name, {
value: Math.round(metric.value),
event_category: 'Web Vitals',
event_label: metric.id,
non_interaction: true,
});
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
Additional Web Vitals
First Contentful Paint (FCP)
Measures when the first text or image is painted.
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
entries.forEach(entry => {
console.log('FCP:', entry.startTime);
});
}).observe({ entryTypes: ['paint'] });
Time to First Byte (TTFB)
Measures server response time.
new PerformanceObserver((entryList) => {
const entries = entryList.getEntries();
entries.forEach(entry => {
console.log('TTFB:', entry.responseStart - entry.requestStart);
});
}).observe({ entryTypes: ['navigation'] });
Optimization Checklist
Performance
- Optimize images (WebP, AVIF, proper sizing)
- Minimize and compress assets
- Use CDN for static assets
- Implement caching strategies
- Remove unused code
Interactivity
- Minimize JavaScript execution time
- Use code splitting
- Implement lazy loading
- Optimize third-party scripts
- Use Web Workers for heavy tasks
Visual Stability
- Set dimensions for images and videos
- Reserve space for dynamic content
- Use font-display: optional
- Avoid inserting content above existing content
- Preload critical resources
Key Concepts
- LCP: Loading performance - optimize images and server response
- FID: Interactivity - minimize JavaScript execution time
- CLS: Visual stability - prevent unexpected layout shifts
- Measurement: Use tools to monitor and track improvements
- Optimization: Focus on the biggest impact areas first
Common Interview Questions
- What are the three Core Web Vitals?
- How do you measure and optimize LCP?
- What causes Cumulative Layout Shift?
- How do you improve First Input Delay?
- What tools do you use to monitor Web Vitals?
Related Topics
- Performance Optimization
- Lighthouse Audits
- Accessibility Guidelines
- SEO Best Practices
- User Experience Design