Skip to content

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

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.

  • 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?”
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 (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.
  • 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.
  • 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.

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.