# Core Web Vitals for PWAs: LCP, INP, and CLS

> What LCP, INP, and CLS measure, their good/needs-improvement thresholds at the 75th percentile, field vs lab data, and the PWA-specific levers that move each metric.

**In one line:** Core Web Vitals are three user-centric metrics — LCP (loading),
INP (responsiveness), and CLS (visual stability). A page passes when the 75th
percentile of real-user visits is "good" on all three: LCP < 2.5s, INP < 200ms,
CLS < 0.1. PWAs have specific levers — service-worker caching, short tasks, and
reserved layout space — that move each one.

## What each metric measures

- **LCP (Largest Contentful Paint)** — time until the largest above-the-fold element
  (usually the hero image, video poster, or a big text block) finishes rendering.
  It answers "did the main content load fast?"
- **INP (Interaction to Next Paint)** — the latency, across the whole visit, from a
  user interaction (tap, click, key press) to the next frame the browser paints. It
  reports a high-percentile value of all interactions, so it captures the *worst*
  responsiveness the user actually felt. INP **replaced FID** as a Core Web Vital in
  March 2024; FID only measured input delay of the first interaction.
- **CLS (Cumulative Layout Shift)** — a unitless score summing unexpected movement of
  visible elements during the page's lifetime. It answers "did things jump around
  while I was reading or tapping?"

## The "good" thresholds

| Metric | Good | Needs improvement | Poor |
|---|---|---|---|
| LCP | ≤ 2.5s | ≤ 4.0s | > 4.0s |
| INP | ≤ 200ms | ≤ 500ms | > 500ms |
| CLS | ≤ 0.1 | ≤ 0.25 | > 0.25 |

Thresholds are evaluated at the **75th percentile** of page loads, split between mobile
and desktop. Passing means the 75th-percentile value is in the "good" band — i.e. at
least 75% of real visits were good.

## Field data vs lab data

- **Field data (RUM)** — real-user measurements collected in the browser via the
  `web-vitals` JS library or aggregated in the Chrome User Experience Report (CrUX).
  This is what Core Web Vitals assessment and Search use. **INP and CLS can only be
  fully measured in the field** because they accumulate across the whole visit.
- **Lab data** — synthetic runs in a controlled environment (Lighthouse, WebPageTest,
  DevTools). Great for debugging and catching regressions in CI, but a single scripted
  load can't reproduce real interaction patterns or network variety.
- Use lab data to find and fix causes; trust field data for the pass/fail verdict.

## PWA-specific levers

- **LCP — cache the critical path in a service worker.** A cache-first or
  stale-while-revalidate strategy lets repeat visits serve the app shell and hero image
  from the Cache Storage API instead of the network, often cutting repeat-visit LCP
  dramatically. Precache the shell on install; set explicit `width`/`height` and
  `fetchpriority="high"` on the LCP image.
- **INP — keep the main thread free of long tasks.** Break up long JavaScript work,
  defer non-urgent updates with `requestIdleCallback`/`scheduler.postTask`, yield with
  `await scheduler.yield()` between chunks, and avoid heavy work inside event handlers.
  Hydration and large client bundles are common INP offenders in app-like PWAs.
- **CLS — reserve space before content arrives.** Set explicit dimensions (or
  `aspect-ratio`) on images, video, and embeds; reserve slots for async content, ads,
  and banners; use `font-display: optional`/`swap` with size-matched fallbacks to
  avoid late-loading-font reflow; never insert content above existing content.

## Practical checklist

- [ ] Measure with field data (CrUX or the `web-vitals` library), not just Lighthouse.
- [ ] Confirm all three metrics are "good" at the **75th percentile** on mobile.
- [ ] Precache the app shell and hero asset in the service worker for fast repeat LCP.
- [ ] Give the LCP image explicit dimensions and `fetchpriority="high"`.
- [ ] Audit long tasks (> 50ms) and break up or defer them to protect INP.
- [ ] Reserve space for every image, embed, ad, and async block to keep CLS < 0.1.
- [ ] Wire a CWV regression check into CI so lab metrics catch issues before release.

## What this means for trust

Fast loading, instant responsiveness, and a stable layout are exactly the cues users
associate with "real apps." A PWA that hits all three Core Web Vitals feels native
rather than web-like — and because Chrome surfaces these metrics in Search ranking
signals, meeting the thresholds also protects discoverability. The PWA toolbox
(service-worker caching, short tasks, reserved space) maps directly onto LCP, INP, and
CLS, so optimizing for installability and optimizing for Core Web Vitals reinforce each
other.