// Performance

Core Web Vitals in Practice: A Step-by-Step Guide to a Faster Website

What LCP, INP and CLS measure, where the usual problems come from, and a repeatable loop for finding and fixing the slowest part of your site.

Core Web Vitals in Practice: A Step-by-Step Guide to a Faster Website

A slow website loses visitors before they have read a word. It also costs rankings, because Google uses page experience signals, and Core Web Vitals are the part of that you can measure and fix. This guide explains the three metrics in plain terms and gives you a loop you can repeat until the numbers are healthy.

The three metrics

Google's "good" thresholds are measured on real visitors, at the 75th percentile.

Good = LCP 2.5s, INP 200ms, CLS 0.1. Write these on the wall.

Metric What it measures Good
LCP (Largest Contentful Paint) How long until the biggest thing on screen has appeared 2.5 seconds or less
INP (Interaction to Next Paint) How quickly the page responds when someone taps or clicks 200 milliseconds or less
CLS (Cumulative Layout Shift) How much the layout jumps around while loading 0.1 or less

In everyday words: is it fast to appear, is it quick to react, and does it stay still.

Field data versus lab data

Two kinds of measurement are easy to confuse:

  • Field data comes from real visitors on real phones and networks. It is what Google uses. You find it in the Core Web Vitals report in Search Console and in PageSpeed Insights.
  • Lab data comes from a simulated run, such as Lighthouse. It is repeatable, which makes it good for debugging, but it is not what ranks you.

Start from field data to learn which pages and which metric are failing. Then use lab tools to find out why.

The loop

flowchart LR
    A["Measure field data"] --> B["Measure lab data"]
    B --> C["Find weakest metric"]
    C --> D{"Which metric?"}
    D -->|LCP| E["Optimize loading"]
    D -->|INP| F["Reduce interaction delay"]
    D -->|CLS| G["Prevent layout shifts"]
    E --> H["Deploy changes"]
    F --> H
    G --> H
    H --> I["Re-measure"]
    I --> C

Change one thing, measure, and move on to the next weakest metric. Fixing several things at once makes it impossible to know what helped.

Fixing LCP

On most sites the largest element is a hero image or a heading. The usual causes of a slow LCP are:

One change at a time, or you will never know what helped.

  1. A heavy image. Serve modern formats such as WebP or AVIF, size them to the space they fill, and compress them. A hero image of several megabytes is the most common single problem.
  2. A late request. If the hero image is discovered only after a stylesheet and a script have loaded, it starts late. Tell the browser early:
<link rel="preload" as="image" href="/img/hero.webp" fetchpriority="high">
<img src="/img/hero.webp" width="1200" height="600" alt="..." fetchpriority="high">
  1. A slow server response. If the HTML itself takes a second to arrive, nothing else can be fast. Cache pages at the edge, and use static or incremental rendering for public pages.
  2. Render-blocking CSS and fonts. Inline the small amount of critical CSS, and load web fonts with font-display: swap.

Do not lazy-load the hero image. Lazy-loading is for images below the fold.

Fixing INP

INP is about the main thread being busy when someone interacts. The causes are almost always JavaScript:

Never lazy-load the hero image. It is the LCP.

  • Long tasks. Anything that blocks the thread for more than about 50 milliseconds delays the next tap. Split big work into smaller chunks, or move it to a web worker.
  • Too much JavaScript. Audit your bundle. Remove libraries you barely use, and load heavy features such as charts or editors only when they are needed.
  • Third-party scripts. Chat widgets, tag managers and trackers run on the same thread as your code. Load them late and remove the ones nobody looks at.
  • Expensive re-renders. In React, avoid re-rendering large trees on every keystroke. Keep state close to where it is used.

Fixing CLS

Layout shift happens when something appears and pushes content down. The fixes are mostly about reserving space:

  • Always set width and height (or aspect-ratio) on images and video.
  • Reserve a fixed slot for ads, banners and embeds.
  • Do not insert content above what the visitor is already reading, such as a cookie banner that pushes the page down.
  • Avoid font swaps that change the text size. Use size-adjust or a similar fallback font.

Where to measure

  • PageSpeed Insights for field and lab data for a single URL.
  • Search Console, Core Web Vitals report for which groups of pages fail.
  • Chrome DevTools, Performance panel to see long tasks and what blocked rendering.
  • The web-vitals library if you want to send your own real-user numbers to analytics.

Make it stick

Performance decays. Every new script and every unoptimised image nudges it back down. Two habits prevent that:

  1. Set a performance budget, for example a maximum JavaScript size per page, and fail the build when it is exceeded.
  2. Run Lighthouse in your CI pipeline so a regression shows up in a pull request instead of in next quarter's traffic report.

Conclusion

You do not need to chase a perfect score. You need the three Core Web Vitals in the green for your real visitors, and a habit that keeps them there. Measure with field data, fix the weakest metric first, and change one thing at a time.

Filed underCore Web VitalsPerformanceSEOFrontend