← All articles
⚡ PerformanceBeginner · 11 min read

Core Web Vitals Explained: LCP, CLS, INP Without the Buzzwords

What each number actually measures, where it comes from, and the specific engineering moves that change it on real user devices.

By Kajal Pansuriya · Reviewed by Kishan Vaghani · Published May 26, 2026

Most teams chase a Lighthouse score without knowing what each metric measures or why Google chose it. The number moves, the team cheers, and a month later the field data has not budged. This post is the working definition of the three Core Web Vitals — and one more you should track even though Google does not grade you on it.

What LCP actually measures

Largest Contentful Paint is the moment the browser paints the largest visible element in the viewport during page load. The element is almost always a hero image, a heading set in a large font, or a background image set on a large container. The number is the timestamp, in milliseconds, from navigation start to that paint.

What blocks it is rarely mysterious. In order of how often it shows up:

The threshold Google uses is 2.5 seconds at the 75th percentile. That means three out of four of your real users need to see the largest element within 2.5 seconds for the metric to be marked good.

What CLS actually measures

Cumulative Layout Shift is the sum of the unexpected movements of visible elements during a five-second window — specifically, the worst five-second window in the session. Each shift is scored by how much of the viewport moved and by how far each element travelled. The score is unitless: 0.1 is the good threshold, 0.25 is poor.

The four causes that account for almost every real case are:

What INP actually measures

Interaction to Next Paint replaced First Input Delay in March 2024. The difference matters: FID only measured the very first interaction of the session, and only the delay before the handler started running. INP looks at every interaction in the session — clicks, taps, key presses — and measures the full time from input to the next visual update. The reported score is approximately the worst interaction in the session.

The threshold is 200 ms at the 75th percentile. Where the number comes from in practice:

The fourth metric Google does not grade you on but you should track

Time to First Byte is the time from navigation start to the moment the first byte of the response arrives. It is not a Core Web Vital, but it bounds every other metric on the page. If your TTFB is 800 ms, your LCP cannot be under 1 second no matter how much you optimise the front end. Track it. The targets that real teams hit on a CDN-backed app are under 200 ms.

High TTFB usually has one of three causes: an origin server that is geographically far from the user with no caching layer in between, a slow database query in the request path, or server-side rendering that waits for data before returning any HTML.

Lab numbers and field numbers tell you different things

A Lighthouse run from a synthetic Chicago datacenter on simulated slow 4G is a development tool. It tells you whether the page is theoretically capable of meeting the thresholds. It does not tell you what your users actually experience.

Field data — collected via the web-vitals library or the Chrome User Experience Report — is the source of truth. A page that scores 95 in Lighthouse can still fail Core Web Vitals in the field if the real user mix is heavy on mid-range Android phones in Pune on a 4G connection that varies between 3 and 25 Mbps. Lab is where you debug; field is where you grade.

What to do first

Measure before you optimise. Install the official web-vitals library, send the metrics to an endpoint you control, and let it run for a week. Look at which of the three metrics is failing at the 75th percentile for your real traffic. Work on that one. Do not chase Lighthouse improvements on the metrics that are already passing.

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

const report = (metric) => {
  navigator.sendBeacon('/vitals', JSON.stringify({
    name: metric.name,
    value: metric.value,
    id: metric.id,
    rating: metric.rating,
    url: location.pathname,
  }));
};

onLCP(report);
onCLS(report);
onINP(report);

The habit that compounds

Scores improve when you optimise for users, not for Lighthouse. The teams that ship genuinely fast products are the ones that watch field metrics weekly, identify the worst-performing metric for the traffic they actually have, and ship one targeted change at a time. That habit beats every clever hack you might find on a tooling leaderboard.

Related reading

The single highest-leverage move on most sites is reducing the JavaScript that ships. The bundle size audit guide walks through the 30-minute process. To collect your own field data without a third party, see the real-user monitoring setup. Both sit in the broader web performance topic.

About the writers

Author

Kajal Pansuriya

Developer Educator, ShareCode

Developer educator at ShareCode. Writes the tutorial track — Python, JavaScript debugging, coding-interview prep, and the everyday code-quality habits that hold up in real codebases.

Python fundamentals & teaching beginnersJavaScript debugging & DevToolsCoding-interview preparationClean code & code review
Reviewed by

Kishan Vaghani

Founder & Lead Engineer, ShareCode

Founder of ShareCode. Writes the engineering deep-dives on this site — WebRTC, Firebase Auth, real-time sync, and the production patterns behind the editor itself.

Real-time collaboration & CRDTsWebRTC & low-latency mediaFirebase authentication & security rulesNext.js & full-stack JavaScript

Working on a slow page right now?

Drop the page URL and your current LCP, CLS, and INP numbers into a code space, share the link with a teammate, and walk through the three metrics one at a time. Most pages have one dominant bottleneck — finding it together takes less than thirty minutes.

Open a code space