Web Performance: Core Web Vitals Deep Dive (LCP, INP, CLS)

Core Web Vitals are Google’s metrics for “how good does this site feel?” — and Google uses them in search ranking. Frontend interviews increasingly probe whether you understand the three vitals, what they measure, and how to optimize each one.

Largest Contentful Paint (LCP)

What: time from navigation start until the largest visible element finishes rendering. Usually a hero image or large headline.

Target: <2.5s for “good,” <4s for “needs improvement.”

What hurts LCP

  • Slow server response (TTFB)
  • Render-blocking CSS or JS
  • Large unoptimized images
  • Lazy-loading the actual hero image
  • Client-side rendering with no SSR

How to fix

  • Server-side rendering or static generation
  • Preload the LCP image: <link rel="preload" as="image">
  • Use modern image formats (WebP, AVIF) with appropriate srcset
  • Inline critical CSS for above-the-fold
  • Defer non-critical JavaScript

Interaction to Next Paint (INP)

INP replaced FID in March 2024. What: the longest delay between any user interaction (click, tap, keypress) and the next paint, throughout the page lifetime. Reported as a single value (worst interaction).

Target: <200ms for “good.”

What hurts INP

  • Long JavaScript tasks blocking the main thread
  • Synchronous third-party scripts (analytics, ads)
  • Heavy event handlers (e.g., expensive setState chains)
  • Large DOM updates triggered by interaction

How to fix

  • Break long tasks into smaller chunks (scheduler.yield or setTimeout)
  • Use requestIdleCallback for non-urgent work
  • Defer or async-load third-party scripts
  • Use useTransition in React 18+ to mark non-urgent updates
  • Virtualize long lists; never re-render thousands of items on click

Cumulative Layout Shift (CLS)

What: total layout shift score during the page’s lifetime. Each shift is scored by impact area × shift distance.

Target: <0.1 for “good.”

What causes CLS

  • Images without explicit width/height
  • Ads or embeds loading and pushing content
  • Custom fonts swapping (FOUT/FOIT)
  • Elements added dynamically (banners, modals) without reserved space
  • Animations on properties other than transform/opacity

How to fix

  • Always set width and height on images and iframes (or use aspect-ratio)
  • Reserve space for ads with min-height
  • Use font-display: optional or preload fonts to minimize swap
  • Animate via transform/opacity, not via top/left/width
  • Avoid inserting content above existing content unless reserved space exists

Measurement

Real User Monitoring (RUM)

  • web-vitals JS library reports actual user experience
  • Send to your analytics (Google Analytics, Datadog, custom endpoint)
  • Segment by device, network, and route

Synthetic monitoring

  • Lighthouse (in Chrome DevTools or CLI)
  • WebPageTest for cross-browser
  • PageSpeed Insights for ranking-relevant metrics
  • Calibre, SpeedCurve for ongoing tracking

The 75th-percentile rule

Google judges sites by the 75th percentile of real users. Your dev machine is not representative. Always look at p75 mobile data, not your laptop.

Frequently Asked Questions

What replaced FID and why?

INP replaced FID in March 2024. FID measured only the first interaction; many users had pages where the first click was fine but later clicks (after JS hydrated and started doing real work) were slow. INP captures the worst case across the session.

Are Core Web Vitals a strong ranking signal?

Material but not dominant. Page experience signals are tiebreakers; content relevance is still primary.

What is a good INP target for SaaS apps?

<200ms for “good.” Many JS-heavy SaaS apps land in 300–500ms; substantial work to fix, but high ROI.

Scroll to Top