Skip to content
All insights

engineering//3 min read

Core Web Vitals for developers: fixing LCP, INP and CLS

Three numbers decide whether a page feels fast: how quickly the main content appears, how quickly it responds, and whether it stays still. What each one measures, what usually breaks it, and the fixes that move it.

Digitat engineeringProduct studio, Mumbai
Web performance engineering dashboard measuring LCP, INP, and CLS performance metrics

In short

  • LCP measures when the main content appears; aim for 2.5 seconds or less.
  • INP measures how fast the page responds to input; aim for 200 milliseconds or less.
  • CLS measures unexpected movement; aim for 0.1 or less.
  • Judge them on real users at the 75th percentile, not on a fast laptop in the office.

Core Web Vitals are Google's three measures of how a page feels to use. They matter for search, but the better reason to care is that each one maps to a real annoyance: waiting for the page, tapping a button that does nothing, or losing your place as the layout jumps.

Metric

Measures

Good

Poor

LCP: Largest Contentful Paint

When the biggest visible element finishes rendering

≤ 2.5 s

> 4 s

INP: Interaction to Next Paint

Delay from a tap, click or key press to the next frame

≤ 200 ms

> 500 ms

CLS: Cumulative Layout Shift

How much visible content moves unexpectedly

≤ 0.1

> 0.25

Google assesses each at the 75th percentile of real visits, split by mobile and desktop. INP replaced First Input Delay as a Core Web Vital in March 2024, and it is much harder to pass, because it counts every interaction rather than only the first.

Measure real users first

Lab tools like Lighthouse are useful for debugging, but they run one load on one device. Field data tells you what customers experience. Search Console's Core Web Vitals report and the Chrome UX Report give you field data for free; the open-source web-vitals library lets you collect your own.

ts
import { onCLS, onINP, onLCP } from "web-vitals";

function send(metric: { name: string; value: number; id: string }) {
  navigator.sendBeacon("/api/vitals", JSON.stringify(metric));
}

onLCP(send);
onINP(send);
onCLS(send);

Fixing LCP

The LCP element is usually a hero image or a large heading. It can only appear once the HTML has arrived, its resources have loaded and nothing is blocking rendering.

  • Make the server fast. Cache pages at the edge where you can; slow database queries before the first byte delay everything else.
  • Make the LCP image discoverable early. A real <img> in the HTML, not a CSS background or an image injected by JavaScript. In Next.js, mark it with priority.
  • Size images for their slot. Serve modern formats at the width they display, with srcset and sizes.
  • Do not lazy-load the hero. Lazy loading is for images below the fold.
  • Trim render-blocking CSS and fonts. Self-host fonts, preload the one used above the fold, and use font-display: swap.

Fixing INP

Poor INP almost always means the main thread is busy when the user interacts. The browser cannot paint a response until the current JavaScript task finishes.

  • Ship less JavaScript. Render on the server what does not need interactivity; every kilobyte of script has to be parsed and run.
  • Break up long tasks. Anything over about 50 ms blocks input. Split work and yield to the browser between chunks.
  • Update the screen first, then do the work. Show the pressed state or a spinner immediately, then run the expensive logic.
  • Defer third-party scripts. Chat widgets, tag managers and A/B testing tools are frequent culprits; load them after the page is interactive.
ts
// Give the browser a chance to paint between chunks of heavy work.
async function processInChunks<T>(items: T[], work: (item: T) => void) {
  for (let i = 0; i < items.length; i++) {
    work(items[i]);
    if (i % 50 === 0) await new Promise((r) => setTimeout(r, 0));
  }
}

Fixing CLS

  • Give every image, video and embed explicit width and height, or an aspect-ratio, so space is reserved before it loads.
  • Reserve room for ads, banners and cookie notices instead of pushing content down when they arrive.
  • Avoid inserting content above existing content unless the user asked for it.
  • Animate with transform and opacity, never with top, height or margin.
  • Match fallback font metrics to your web font so text does not reflow when it loads.
Speed is a feature people feel before they can name it. Measure it where they are: on their phones.

A working order

  1. Get field data and find the worst pages by traffic.
  2. Fix CLS first; it is usually the quickest win.
  3. Fix LCP on your top templates: home, product or article, and pricing.
  4. Profile interactions in the Performance panel and break up the long tasks behind poor INP.
  5. Add a performance budget to CI so the gains stick.

Tags

  • Performance
  • Core Web Vitals
  • Next.js
  • SEO
  • Frontend

Share

LinkedInX
Written byDigitat engineeringProduct studio, Mumbai

Have a product worth writing about?

Tell us where it is today. We reply within 12 hours.