Understanding The Core Web Vitals


As frontend developers, we don’t just care about features but we also care a whole lot about user experience. This is because it can get really frustrating to a user when a page looks so beautiful but behaves weirdly during user interaction like page scroll, responds late to user input, or animations don’t play smoothly. These micro-frustrations are what the Core Web Vitals (CWV) aim to measure and eliminate.
For instance, if you have ever wondered:
Why is my Lighthouse score so low?
Why did Google Search Console flag my site for poor performance?
How do I actually fix the layout shift on my page?
This article aims to break these all down for you, with real examples, and actionable tips. 😉
So, What Really Are Core Web Vitals?
Core Web Vitals are important metrics that help us measure the user experience (UX) of a website or page, so we can have an idea of how good or bad the UX is. They focus on three main areas; loading performance, interactivity, and visual stability. These metrics help ensure that websites are fast, responsive, and visually stable for users.
They include:
LCP (Largest Contentful Paint): this measures how fast the page takes to load.
FID (First Input Delay): this measures how quickly a page becomes interactive.
CLS (Cumulative Layout Shift): this measures the visual stability of a page.
These metrics aren’t just random. They represent actual user pain points such as these for the cases above respectively:
LCP: “The page took too long to load”.
FID: “I tapped on a button but nothing happened”.
CLS: “The page layout keeps jumping/skipping”.
And, Why Do They Matter?
Ranking factor: Google uses Core Web Vitals for Search Engine Optimization (SEO). Pages with low scores might rank lower.
Perception: A page that "feels" fast performs better, even if it isn't technically faster.
Retention & UX: Poor scores means higher bounce rate, which also means a long list of users will most likely be lost.
Let’s Go!
1. Largest Contentful Paint (LCP)
LCP measures how long it takes for the biggest content element at the top of the page (like a main image, <h1>
, or video thumbnail) to load completely.
To achieve a good LCP score, aim for under 2.5 seconds load time, measured at the 75th percentile across both mobile and desktop.
PS: It’s not when the page starts loading, but when it feels meaningfully loaded.
What Counts as “Contentful”?:
The largest visible element/tag within the viewport:
<img>
<video>
<h1>
or any large text blockBackground images via
url()
(excluding CSS gradients or pseudo-elements)
For instance, if your homepage has a large hero image and title, and that image takes 4 seconds to appear due to render-blocking CSS or JS, your LCP is 4s. That is too slow to even imagine, for real.
How to Improve LCP:
Issue | Fix |
Slow server response (or Time to First Byte; TTFB) | Use Server-Side Rendering (SSR) or Edge rendering, CDN, HTTP/2 |
Unoptimized images | Serve WebP/AVIF, compress asset, set responsive sizes |
Render-blocking CSS/JS | Inline critical CSS, defer non-critical JS |
Client-side hydration delay (can be seen in React/Next.js) | Use static/SSR for the top part of the page, load non-essential parts after hydration. |
Too many web fonts | Use font-display: swap , preload key fonts |
Tools to Measure:
Chrome DevTools (LCP marker, under the Performance tab)
Lighthouse (Performance tab)
PageSpeed Insights
Web Vitals extension
web-vitals
npm package
2. First Input Delay (FID)
FID measures the time between user interaction and the browser responding.
Applies to first interaction, for instance, tap, click, or keypress (excluding scroll).
It’s not about visual feedback. It’s about when the JavaScript event handler starts.
To achieve a good FID score, aim for under 100 milliseconds.
Why Does It Matter?:
Just imagine that your page looks ready, but the JS thread is still blocked and parsing about 1mb of bundled code. Then a user taps the “Add to Cart” button but nothing happens for a full second.
Now that’s a really poor FID, which would in essence translate to poor UX.
How to Improve FID:
Issue | Fix |
Long JavaScript tasks | Break tasks using requestIdleCallback , setTimeout |
Heavy main thread blocking tasks | Use Web Workers, reduce bundle size |
Too much third-party JS | Defer or lazy-load scripts like analytics, chat widgets, and other non-essential scripts |
Too many event listeners | Debounce listeners, use delegation |
Large hydration window | Use progressive hydration, avoid blocking scripts during hydration |
Tools to Measure:
FID can only be measured in real-world situations and is not available in lab tools like Lighthouse. To measure, use Real User Monitoring (RUM) tools designed to capture real-world user interactions and provide insights into how users experience your website, or Web Vitals API to track it in production.
3. Cumulative Layout Shift (CLS)
CLS measures how much the page layout shifts during the entire lifespan of the page, especially while it’s still loading. It quantifies unexpected movement of elements.
For instance, think of:
Images loading and pushing content down.
Ads injecting a weird space on a page.
Fonts swapping and resizing.
To achieve a good CLS score, aim for under 0.1.
Imagine if:
A user gets on a page with the intention of tapping a “Pay Now” button, but just before they tap the button, the page jumps because an image or banner loaded. And then, they accidentally click the “Subscribe to newsletter” button. As simple as it sounds, it is really bad and can even get worse!
How to Fix CLS:
Cause | Fix |
Images without dimensions | Always set width and height or use aspect-ratio |
Dynamic ads/content | Reserve space with CSS or skeleton loaders |
Web fonts causing reflow | Use font-display: swap , preload fonts |
Lazy loading above-the-fold content | Preload or use priority in Next.js <Image> |
DOM injected banners/modals | Animate into reserved space or load off-screen |
CLS Components:
Cumulative Layout Shift is calculated as the sum of all layout shift scores that occur throughout the entire lifespan of a page. This metric is crucial for understanding how much the page layout changes unexpectedly while the page is loading or even after it has fully loaded.
To break it down further, a single shift score is determined by multiplying two factors: the impact fraction and the distance fraction.
Impact fraction represents the portion of the viewport that is affected by the shift. For example, if the shift impacts 25% of the viewport, the impact fraction would be 0.25.
Distance fraction measures how far the elements on the page have moved relative to the viewport.
Mathematically;
CLS = sum of all layout shift scores.
A single shift score = impact fraction × distance fraction.
By understanding and addressing these components, developers can effectively reduce CLS and improve user experience. It is important to ensure that all elements on a page load smoothly and predictably, minimizing any unexpected movements that could disrupt user interactions.
How to Measure Core Web Vitals
Lab Tools (Good for Debugging)
Chrome Lighthouse (DevTools)
WebPageTest
PageSpeed Insights
Lighthouse CI for CI/CD pipelines
PS: I wrote about lighthouse here and the DevTools here.
Field Tools (Good for Real User Monitoring)
Core Web Vitals report in the Google Search Console.
Chrome UX Report (CrUX).
Web-vitals JS Library (
npm i web-vitals
oryarn add web-vitals
).Analytics tools: GA4, SpeedCurve, New Relic, Datadog, Vercel Analytics.
CWV in Frameworks Like Next.js (React)
If you’re using Next.js, you can measure Core Web Vitals natively with the reportWebVitals
function llike this:
// _app.tsx
export function reportWebVitals(metric) {
if (metric.name === 'LCP' || metric.name === 'FID' || metric.name === 'CLS') {
fetch('/analytics', {
method: 'POST',
body: JSON.stringify(metric),
});
}
}
You can also hook this into your analytics or logging dashboard.
In Conclusion
As frontend developers, our job doesn’t stop at pushing pixel perfect screens. We are always tasked with delivering great user experiences, and have a very important role to play in user retention at any business we find ourselves in. If our pages shift, lag, or behave weirdly, users would always notice and would be scared away.
So let’s stop guessing and start measuring! Let’s build fast, ship smooth, and think like our users always.
It’s customer first! 😇💪
References & Further Reading
Subscribe to my newsletter
Read articles from Gospel Chinyereugo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Gospel Chinyereugo
Gospel Chinyereugo
I am a highly skilled Full Stack Software Engineer (frontend heavy) with a track record of success in the banking/fintech, health-tech, e-commerce, event tech, and CRM industries. With over half a decade of experience, I bring a wealth of experience in development, advocacy, problem-solving and architecture design.