Back to all articles

Mastering Core Web Vitals: A Practical Guide to Optimizing INP & LCP

Demystifying Google's latest Core Web Vitals metric — Interaction to Next Paint (INP) — along with concrete techniques for slashing Largest Contentful Paint (LCP).

Nasikh Mahamood CL

Nasikh Mahamood CL

·9 min read
Share:𝕏in

With Google's official deprecation of First Input Delay (FID) in favor of Interaction to Next Paint (INP), performance engineering entered a new era.

FID only measured how quickly the browser reacted to the very first click on a page. INP evaluates the latency of every single user interaction across the entire lifecycle of a visit.

If your web application freezes for 250ms when a user opens a modal or sorts a table after 10 minutes of browsing, your INP fails.

Here is how we diagnose and conquer INP and LCP in modern web applications.

#1. What Really Causes Bad INP?

INP measures the duration between when a user interacts (taps, clicks, keystrokes) and when the browser paints the updated visual frame.

The 3 phases of an interaction are:

  1. Input Delay: Time waiting for previous main thread tasks to clear before event listeners execute.
  2. Processing Time: The time your JavaScript event callback takes to run.
  3. Presentation Delay: The time required to recalculate styles, layout, and composite pixels on screen.

#The Fix: Yielding to the Main Thread

If an event handler has to execute heavy operations, yield control back to the browser so it can paint intermediate visual feedback:

async function handleFilterChange(filterValue) {
  // 1. Immediately provide visual feedback
  setPendingUI(true);

  // 2. Yield to allow the browser to paint the loading state
  await new Promise((resolve) => setTimeout(resolve, 0));

  // 3. Perform the computationally heavy task
  computeFilteredResults(filterValue);
}

In modern browsers, you can use scheduler.yield():

if ('scheduler' in window && 'yield' in window.scheduler) {
  await window.scheduler.yield();
}

#2. Optimizing Largest Contentful Paint (LCP)

LCP measures when the largest visual block (usually hero text, background image, or banner) renders within the viewport.

To hit sub-2.5s LCP:

  • Preload hero assets: Use <link rel="preload"> or Next.js priority prop on your <Image />.
  • Eliminate render-blocking CSS: Keep critical CSS inline and defer unused fonts and analytics scripts.
  • Serve images in modern WebP / AVIF formats: Compress images to target sub-100KB payloads without visible fidelity loss.

#Summary

Don't wait for your users to complain about sluggish responsiveness. Use the Chrome Web Vitals extension in staging and observe real-user metrics (RUM) in production to ensure smooth 60fps experiences.

Nasikh Mahamood CL

Written by Nasikh Mahamood CL

SDE 2 at CAMS. Building high-performance SaaS applications and sharing lessons.