What Are Core Web Vitals?
Core Web Vitals are a set of three performance metrics defined by Google that measure real-world user experience on web pages. They directly impact search rankings and represent what Google considers the most important aspects of page experience.
As a QA engineer, understanding these metrics is essential because:
- They affect SEO rankings (search visibility)
- They correlate with user engagement and conversion rates
- They provide objective, measurable criteria for performance acceptance testing
- They are increasingly included in performance budgets and release criteria
The Three Core Web Vitals
LCP — Largest Contentful Paint
What it measures: The time from when the page starts loading to when the largest content element in the viewport is rendered.
Good threshold: Under 2.5 seconds
What counts as the “largest element”:
- Images (
<img>,<image>inside SVG) - Video poster images
- Background images loaded via
url() - Block-level text elements (
<h1>,<p>, etc.)
Common causes of poor LCP:
- Slow server response time (high TTFB)
- Render-blocking JavaScript and CSS
- Slow resource load times (large images, unoptimized fonts)
- Client-side rendering delays (SPA frameworks)
INP — Interaction to Next Paint
What it measures: The responsiveness of the page to user interactions (clicks, taps, key presses) throughout its entire lifecycle. INP is the worst interaction latency, ignoring outliers.
Good threshold: Under 200 milliseconds
How it works:
- User clicks a button
- Browser processes the event handler (JavaScript)
- Browser updates the visual display
- INP measures the total time from step 1 to step 3
Common causes of poor INP:
- Long-running JavaScript tasks blocking the main thread
- Excessive DOM size (>1500 elements)
- Complex event handlers without optimization
- Third-party scripts competing for main thread time
CLS — Cumulative Layout Shift
What it measures: The total of all unexpected layout shifts that occur during the entire lifespan of the page. A layout shift happens when a visible element changes its position from one frame to the next without user interaction.
Good threshold: Under 0.1
CLS calculation:
Layout Shift Score = Impact Fraction × Distance Fraction
- Impact fraction: The area of the viewport affected by the shift
- Distance fraction: How far the element moved relative to the viewport
Common causes of poor CLS:
- Images and ads without explicit width/height dimensions
- Dynamically injected content above existing content
- Web fonts causing text to resize (FOIT/FOUT)
- Late-loading third-party embeds
Measuring Core Web Vitals
Lab Data (Development/Testing)
Lab data is collected in a controlled environment. It is reproducible but does not represent real-user conditions.
| Tool | LCP | INP | CLS | Notes |
|---|---|---|---|---|
| Chrome DevTools (Performance tab) | Yes | Yes | Yes | Most detailed |
| Lighthouse | Yes | No (uses TBT) | Yes | Aggregate scores |
| PageSpeed Insights | Yes | Yes | Yes | Lab + field data |
| WebPageTest | Yes | Partial | Yes | Multi-location testing |
Field Data (Real Users)
Field data comes from actual users visiting your site. It reflects real conditions but requires traffic volume.
| Source | Data Type | Availability |
|---|---|---|
| Chrome UX Report (CrUX) | 28-day rolling average | Public (sites with enough traffic) |
| PageSpeed Insights | CrUX data with origin summary | Public |
| Search Console | Core Web Vitals report | Site owners only |
| web-vitals JavaScript library | Real-time per-user data | Requires implementation |
Using DevTools Performance Tab
- Open DevTools > Performance tab
- Click the gear icon and enable Web Vitals
- Click Record and reload the page
- Stop recording after the page fully loads
- Look for the Web Vitals lane showing LCP, CLS markers
- The Summary pane shows timing breakdowns
Quick Check with PageSpeed Insights
Navigate to pagespeed.web.dev and enter your URL. The report shows:
- Field data (if available): Real-user Core Web Vitals from the past 28 days
- Lab data: Simulated performance from a mid-tier mobile device on 4G
- Diagnostics: Specific issues with recommended fixes
- Passed audits: What is already working well
Testing Strategies for Core Web Vitals
LCP Testing Checklist
- Measure LCP on the landing page, product pages, and blog posts
- Test with throttled network (Slow 3G, Fast 3G, 4G)
- Test with CPU throttling (4x, 6x slowdown)
- Verify LCP element is the intended hero image/text, not an unexpected element
- Check that LCP does not regress after new deployments
- Test with empty cache and primed cache
INP Testing Checklist
- Click every interactive element and note if any feel sluggish
- Test form submissions, dropdown menus, and modal openings
- Test while the page is still loading (partially loaded state)
- Use DevTools Performance tab to identify long tasks (>50ms)
- Test with CPU throttling to simulate lower-end devices
CLS Testing Checklist
- Watch the page load from start to finish — note any visual jumps
- Scroll through the entire page watching for shifts
- Test with slow network to see layout shifts during progressive loading
- Verify all images have explicit width and height attributes
- Test with ad blockers disabled (ads are a common CLS source)
- Check font loading — does text reflow when web fonts load?
Exercise: Core Web Vitals Audit
Perform a Core Web Vitals audit on a website of your choice (your company’s site, a personal project, or a well-known public site).
Step 1: Collect Lab Data
Open the site in Chrome with DevTools:
- Go to the Performance tab
- Enable Web Vitals in settings
- Set throttling: CPU 4x slowdown, Fast 3G network
- Record a fresh page load (clear cache first with Ctrl+Shift+Delete)
- Record the following values:
| Metric | Value | Good Threshold | Pass/Fail |
|---|---|---|---|
| LCP | ___s | <2.5s | |
| CLS | ___ | <0.1 | |
| TBT (proxy for INP) | ___ms | <200ms |
Step 2: Identify LCP Element
In the Performance recording:
- Find the LCP marker in the Web Vitals lane
- Click on it to see which element triggered LCP
- Document: What is the LCP element? Is it the intended hero content?
Step 3: Find Layout Shifts
- In the Performance recording, look for pink bars in the Experience row
- Click each layout shift to see which elements moved
- Document each shift: What element? How far did it move? What caused it?
Step 4: Test Interactions
- Record a new performance session
- Click on 5-10 interactive elements (buttons, links, menus, form fields)
- Look for long tasks (yellow blocks >50ms) triggered by your interactions
- Document any interaction that takes more than 200ms to respond visually
Solution: Sample Audit Report
Site audited: example-ecommerce.com (homepage)
Lab Results (Chrome, CPU 4x, Fast 3G):
| Metric | Value | Threshold | Status |
|---|---|---|---|
| LCP | 3.8s | <2.5s | FAIL |
| CLS | 0.24 | <0.1 | FAIL |
| TBT | 890ms | <200ms | FAIL |
LCP Analysis:
- LCP element: Hero banner image (2.4MB JPEG)
- Root cause: Image is not optimized, no responsive srcset, no preload hint
- Fix: Convert to WebP, add
loading="eager", add<link rel="preload">, implement srcset for responsive sizes
CLS Issues Found:
| Element | Shift Score | Cause |
|---|---|---|
| Hero image | 0.12 | No width/height attributes |
| Ad banner | 0.08 | Injected after page load |
| Cookie consent | 0.04 | Pushes content down |
- Fix: Add explicit dimensions to images, reserve space for ads with CSS, use overlay for cookie consent instead of pushing content
INP/TBT Issues:
- Main thread blocked for 450ms by analytics bundle
- Product carousel initialization blocks for 320ms
- Third-party chat widget adds 120ms to page load
- Fix: Defer analytics, lazy-load carousel, load chat widget on user interaction
Recommendations priority:
- Optimize hero image (LCP: expected improvement from 3.8s to ~1.8s)
- Add image dimensions (CLS: expected improvement from 0.24 to ~0.04)
- Defer non-critical JavaScript (TBT: expected improvement from 890ms to ~200ms)
Automated Core Web Vitals Monitoring
For ongoing quality assurance, integrate Core Web Vitals into your CI/CD pipeline:
# Using Lighthouse CI
npm install -g @lhci/cli
# Run Lighthouse with assertions
lhci autorun --config=lighthouserc.json
Example lighthouserc.json with Core Web Vitals thresholds:
{
"ci": {
"assert": {
"assertions": {
"largest-contentful-paint": ["error", {"maxNumericValue": 2500}],
"cumulative-layout-shift": ["error", {"maxNumericValue": 0.1}],
"total-blocking-time": ["error", {"maxNumericValue": 200}]
}
}
}
}
This fails the build if Core Web Vitals exceed thresholds, preventing performance regressions from reaching production.
Key Takeaways
- Core Web Vitals consist of three metrics: LCP (loading), INP (interactivity), and CLS (visual stability)
- INP replaced FID in March 2024 and measures responsiveness across the entire page lifecycle
- Use both lab data (DevTools, Lighthouse) and field data (CrUX, Search Console) for a complete picture
- Each metric has specific testing strategies — do not just check the aggregate score
- Integrate Core Web Vitals thresholds into CI/CD to prevent regressions
- Poor Core Web Vitals directly impact SEO rankings and user engagement