Performance
INP, LCP, CLS: How to Improve Core Web Vitals Step-by-Step
Concrete steps to improve each Core Web Vital so your site passes and stays in the green—from measurement to fix order.

Core Web Vitals (LCP, INP, CLS) are the metrics that matter for UX and search. This guide walks you through improving each one step by step: how to measure, what to fix first, and how to re-check so your site stays in the green. Whether you're new to performance or tuning an existing app, you'll have a clear order of operations.
Why Core Web Vitals and in what order
LCP (Largest Contentful Paint) affects perceived load speed; INP (Interaction to Next Paint) affects how responsive the page feels; CLS (Cumulative Layout Shift) affects visual stability. Search engines use these (and related metrics) as signals. Fix LCP first (biggest perceived impact), then CLS (often quick wins), then INP (often requires more code and measurement). After each change, re-run Lighthouse or check CrUX so you see the effect and don't regress.
LCP: get the largest element fast
LCP is the load time of the largest visible content (usually an image or text block above the fold).
- Step 1: Identify the LCP element (Lighthouse "Largest Contentful Paint" or DevTools Performance).
- Step 2: Make sure it's in the initial HTML and not blocked—avoid loading it only after JS runs. If it's an image, don't lazy-load it above the fold.
- Step 3: Optimize the resource: resize the image to display size, serve WebP/AVIF, use priority or preload so the browser fetches it early. For Next.js, use
priorityon the LCP image. - Step 4: Improve server response (TTFB) with caching or a faster host so the HTML and LCP resource start quickly.
Re-measure; LCP should drop into the "good" range (under about 2.5s).
Beginner tip: In Lighthouse, click the LCP element in the timeline to see what it is. Often it's the hero image or main heading—optimize that first.
INP: keep interactions responsive
INP measures responsiveness to clicks and taps (how long until the next paint after input).
- Step 1: Find long tasks and heavy handlers in the Performance panel or with Lighthouse.
- Step 2: Reduce JS: code-split and lazy-load below-the-fold or non-critical code; defer third-party scripts (analytics, chat) until after load or on interaction.
- Step 3: Break up long work: move heavy logic to a worker or chunk it (e.g.
requestIdleCallback, or yielding in loops) so the main thread stays free. - Step 4: Optimize event handlers: keep them short; defer non-critical updates or use passive listeners where possible.
Re-test; INP should stay low so interactions feel instant.
Expert tip: Use Chrome's "Long tasks" and "Main thread" view to see what blocks input. Often the culprit is a large bundle or a single heavy handler—fix that before micro-optimizing.
CLS: prevent layout shift
CLS is the cumulative layout shift from unexpected resizing or movement.
- Step 1: Find shifting elements in Lighthouse (Experience → Cumulative Layout Shift) or the layout shift regions in DevTools.
- Step 2: Images: always set width and height (or aspect-ratio) so space is reserved before the image loads. Use
aspect-ratioor explicit dimensions in CSS or on<img>/ Next.jsImage. - Step 3: Fonts: use font-display and match fallback metrics (size, line-height) so text doesn't jump when the custom font loads.
- Step 4: Dynamic content (ads, embeds): reserve space with a min-height or aspect-ratio container so the layout doesn't jump when they load.
Re-run; CLS should be under about 0.1.
Summary
- LCP: Identify the LCP element, keep it in initial HTML, optimize size/format/priority, improve TTFB.
- INP: Reduce and chunk JS, keep handlers light, defer third-party scripts.
- CLS: Reserve space for images (width/height or aspect-ratio), fonts (fallbacks), and dynamic content.
Fix in that order and re-measure so your site stays in the green.