Core Web Vitals and INP: A Hands-On Optimisation Guide
Core Web Vitals reduces a page's user experience to three measurable signals: loading speed, visual stability and interaction responsiveness. With INP replacing FID in 2024, the trio now reflects real user behaviour far more honestly.
The three metrics and their thresholds
| Metric | What it measures | Good | Poor |
|---|---|---|---|
| LCP | Time for the largest content element to appear | ≤ 2.5 s | > 4.0 s |
| CLS | Unexpected layout shifts | ≤ 0.1 | > 0.25 |
| INP | Worst response time to an interaction | ≤ 200 ms | > 500 ms |
These thresholds must be met for 75% of sessions. Evaluation is by percentile, not average — the minority having a bad experience is not ignored.
LCP: almost always the same five causes
After hundreds of audits, the vast majority of LCP problems come down to one of five causes:
- Slow server response (TTFB). On shared hosting a TTFB above 800 ms is common. A cache layer and PHP-FPM tuning solve most cases.
- Unoptimised hero image. A 1.4 MB JPEG can drop to 180 KB as AVIF. Add
fetchpriority="high"and never setloading="lazy"on the hero image. - Font blocking. Use
font-display: swap, preload the critical font and cut the number of variants to two. - Render-blocking CSS/JS. Inline critical CSS and defer the rest.
- Client-side rendering. If content is produced by JavaScript, LCP is necessarily delayed. Prefer server-side rendering or static generation.
CLS: invisible, but the easiest metric to fix
Layout shift usually comes from four sources:
- Media without dimensions. Add
widthandheightto every<img>and<video>; scaling with CSS is fine, the browser just needs the aspect ratio in advance. - Banners injected later. Take cookie notices and announcement bars out of the flow with
position: fixed. - Web font swap. Use
size-adjustandascent-overrideto bring the fallback font close to the real font's metrics. - Ads and embeds. Give the container a
min-height.
INP: the newest and most misunderstood metric
INP measures close to the worst of all interactions across the page's lifetime. A single slow click can ruin the whole score. It has three components: input delay, processing time and presentation delay.
Practical fixes
- Break up long tasks. Any JavaScript task over 50 ms blocks the main thread. Split work with
scheduler.yield()orawait new Promise(r => setTimeout(r, 0)). - Give visual feedback before doing the work. On click, first put the button into a loading state and defer the heavy work to the next frame. Perceived latency drops dramatically.
- Audit third-party scripts. Chat widgets, heatmaps and A/B testing tools are the most common INP killers. Load each with
asyncand question whether it is truly needed. - Lighten event listeners. Use
passive: trueonscrollandresizelisteners and wrap work inrequestAnimationFrame. - Control DOM size. Style recalculation becomes expensive on pages above 1,500 nodes.
Measuring correctly: lab versus field
Do not confuse the two data types. Lab data (Lighthouse, the PageSpeed Insights score) is a simulation under fixed conditions, ideal for fast feedback during development. Field data (CrUX, the Search Console Core Web Vitals report, your own RUM setup) comes from real users and is what is used for ranking.
The practical approach: look at Lighthouse while building, look at field data when deciding. Because field data uses a 28-day rolling window, seeing the effect of a change takes about four weeks — be patient and resist shipping a new intervention every week.
Set a performance budget
Optimisation is not a one-off project but a lasting discipline. A simple budget is enough:
- Total JavaScript: under 150 KB compressed
- Total image weight: under 400 KB above the fold
- Third-party requests: fewer than 10
- LCP: under 2.0 s (keep the target below the threshold so you have headroom)
Wire these into CI and performance will not quietly rot six months later.
Frequently Asked Questions
Does a PageSpeed score of 100 guarantee SEO results?
No. The score is computed in lab conditions; Google uses real user data (CrUX) for ranking. Sites exist with a score of 100 that are slow for actual users. The target is passing the thresholds in field data, not the score.
What should INP be below?
INP should be under 200 milliseconds for 75% of page loads. The 200–500 ms range is "needs improvement" and above 500 ms is considered "poor".