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 block

  • Background 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:

IssueFix
Slow server response (or Time to First Byte; TTFB)Use Server-Side Rendering (SSR) or Edge rendering, CDN, HTTP/2
Unoptimized imagesServe WebP/AVIF, compress asset, set responsive sizes
Render-blocking CSS/JSInline 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 fontsUse 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:

IssueFix
Long JavaScript tasksBreak tasks using requestIdleCallback, setTimeout
Heavy main thread blocking tasksUse Web Workers, reduce bundle size
Too much third-party JSDefer or lazy-load scripts like analytics, chat widgets, and other non-essential scripts
Too many event listenersDebounce listeners, use delegation
Large hydration windowUse 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:

CauseFix
Images without dimensionsAlways set width and height or use aspect-ratio
Dynamic ads/contentReserve space with CSS or skeleton loaders
Web fonts causing reflowUse font-display: swap, preload fonts
Lazy loading above-the-fold contentPreload or use priority in Next.js <Image>
DOM injected banners/modalsAnimate 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 or yarn 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

2
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.