Google's PageSpeed Insights still grades a page from 0 to 100, but in 2026 that number is only a proxy. What actually moves rankings and conversions is Core Web Vitals — the real-user speed and stability metrics Google measures in the field. This guide (Part 1 of 2) explains what to measure in 2026 and how to fix the issues that drag a page down.
A high Lighthouse score is a lab estimate from one simulated load on one device. Core Web Vitals come from the Chrome User Experience Report (CrUX) — anonymized data from real Chrome users on real networks and devices. The two often disagree, and field data is what counts for Search.
Core Web Vitals in 2026
There are three Core Web Vitals. The biggest change since older guides: INP (Interaction to Next Paint) replaced FID (First Input Delay) as a Core Web Vital on 12 March 2024. FID only measured the delay before the first interaction; INP measures responsiveness across the whole visit, so it is far more representative of real UX and much harder to game.
| Metric | What it measures | Good (75th pct) | Needs work | Top fixes |
|---|---|---|---|---|
| LCP — Largest Contentful Paint | Loading: time to render the largest visible element | ≤ 2.5 s | 2.5–4.0 s | Faster TTFB, preload + fetchpriority, modern image formats |
| INP — Interaction to Next Paint | Responsiveness: latency of user interactions | ≤ 200 ms | 200–500 ms | Break up long tasks, cut JS, reduce third-party scripts |
| CLS — Cumulative Layout Shift | Visual stability: unexpected layout movement | ≤ 0.1 | 0.1–0.25 | Size images/embeds, reserve ad space, font-display: swap |
"Good" means the 75th percentile of page loads meets the threshold — you need roughly 75% of real visits to pass, not just your own test run.
Lab data vs. field data — and the tools for each
- Lab data is collected in a controlled environment (one device, one throttled connection). It is reproducible and great for debugging, but it is not what users experience.
- Field data is real-user monitoring (RUM) aggregated in CrUX. It is what Google uses to assess Core Web Vitals for ranking.
Use the right tool for the job:
- PageSpeed Insights — shows both lab (Lighthouse) and 28-day field (CrUX) data side by side for a URL.
- Lighthouse — in Chrome DevTools or via the CLI (
npx lighthouse <url>) for lab audits and CI gating. - Chrome DevTools Performance panel — record a trace to find the long tasks that hurt INP.
- WebPageTest — multi-location, real-device testing with filmstrip and waterfall analysis.
- Search Console → Core Web Vitals report — field data grouped by URL pattern across your whole site.
- The
web-vitalsJS library — capture LCP/INP/CLS from your own users in production.
Improving LCP (Largest Contentful Paint)
LCP is usually a hero image, a large heading, or a big text block above the fold. The most effective levers:
- Cut server response time (TTFB). Cache rendered pages or fragments, add a CDN, and reduce N+1 database queries. On Django, watch for unused or duplicated ORM queries and add
select_related/prefetch_related. - Prioritize the LCP resource. Preload it and mark it high priority so the browser fetches it early.
- Serve modern, right-sized images. Use AVIF or WebP,
srcsetfor responsive sizing, and never lazy-load the LCP image. - Eliminate render-blocking CSS/JS. Inline critical CSS, defer the rest, and load non-critical JavaScript with
defer/async.
<!-- Preload + prioritize the LCP image; serve modern formats responsively -->
<link rel="preload" as="image" href="/img/hero.avif" fetchpriority="high" />
<picture>
<source type="image/avif"
srcset="/img/hero-800.avif 800w, /img/hero-1600.avif 1600w" sizes="100vw" />
<source type="image/webp"
srcset="/img/hero-800.webp 800w, /img/hero-1600.webp 1600w" sizes="100vw" />
<img src="/img/hero-1600.jpg" width="1600" height="900"
alt="Product dashboard" fetchpriority="high" decoding="async" />
</picture>
<!-- Below-the-fold images: lazy-load AND keep dimensions to avoid layout shift -->
<img src="/img/feature.webp" width="640" height="360"
loading="lazy" decoding="async" alt="Feature screenshot" />Improving INP (Interaction to Next Paint)
INP is dominated by JavaScript running on the main thread. To keep interactions under 200 ms:
- Break up long tasks. Split any work over 50 ms into smaller chunks and yield to the main thread with
await scheduler.yield()(orsetTimeout/requestIdleCallback) so input can be processed. - Ship less JavaScript. Code-split, tree-shake, and remove unused libraries — heavy hydration is a common INP killer.
- Tame third-party scripts. Chat widgets, tag managers, and A/B tools run on your main thread; load them lazily or move them to a web worker.
- Debounce expensive handlers (search-as-you-type, scroll, resize) and push heavy work off the critical path.
- Use
content-visibility: autoon off-screen sections so the browser can skip their rendering work until they are needed.
Improving CLS (Cumulative Layout Shift)
CLS happens when content moves after it first paints. Reserve space for everything that loads late:
- Always set
width/height(oraspect-ratio) on images, video, and iframes so the browser reserves the box before the asset arrives. - Reserve space for ads, embeds, and banners with a min-height container instead of letting them push content down on load.
- Prevent font-swap shift with
font-display: swapplus a preloaded, well-matched fallback so reflow on font load is minimal. - Never insert content above existing content (cookie bars, "you may also like" injections) unless the user explicitly triggered it.
/* Reserve the image box even before the file loads */
img, video { max-width: 100%; height: auto; }
.media { aspect-ratio: 16 / 9; width: 100%; }
/* Preload the font and swap so text is visible immediately */
@font-face {
font-family: "Inter";
src: url("/fonts/inter.woff2") format("woff2");
font-display: swap;
}Quick wins for every page
Beyond the three vitals, a few server- and asset-level changes help every metric:
- Enable Brotli or gzip compression for text assets (HTML, CSS, JS, SVG).
- Serve over HTTP/2 or HTTP/3 so many resources can download in parallel.
- Set long-lived cache headers on fingerprinted static files, with a short TTL on HTML.
- Minify CSS/JS/HTML and subset fonts to the glyphs you actually use.
- Self-host or
preconnectto critical third-party origins.
# Long cache for hashed/static assets, short cache for HTML
location ~* \.(?:css|js|woff2|avif|webp|jpg|png|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location / {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
# Brotli + gzip for text assets
brotli on;
brotli_types text/css application/javascript image/svg+xml;
gzip on;
gzip_types text/css application/javascript image/svg+xml;Where to go next
Page speed is never "done" — measure with field data, fix the worst-offending metric, then re-measure. In Part 2 of this series we continue with more advanced techniques for squeezing out the last seconds.
For related reading, see our guide to on-page SEO factors (speed is one ranking signal among many) and hosting Django on Nginx with uWSGI for high performance for server-side tuning. If you would rather hand it off, our team has spent 12+ years and 50+ projects shipping fast web applications and Django builds that pass Core Web Vitals.
Frequently Asked Questions
What replaced FID in Core Web Vitals?
INP (Interaction to Next Paint) replaced FID (First Input Delay) as a Core Web Vital on 12 March 2024. INP measures the latency of all interactions during a visit, not just the first one, so it reflects real responsiveness far better.
What are good LCP, INP, and CLS scores?
At the 75th percentile of real-user loads: LCP ≤ 2.5 s, INP ≤ 200 ms, and CLS ≤ 0.1. Roughly 75% of your visits need to meet each threshold for the page to be rated "good."
Why is my field score worse than my Lighthouse score?
Lighthouse is lab data — one simulated load on one device and connection. Field data (CrUX) aggregates real users on slower networks, older phones, and cold caches. Google ranks on field data, so trust CrUX and Search Console over a single lab run.
How do I improve LCP quickly?
Identify the LCP element in PageSpeed Insights, then preload it with fetchpriority="high", serve it as AVIF/WebP at the right size, never lazy-load it, and cut server response time with caching and a CDN.
Do images really cause layout shift?
Yes — images without width/height (or aspect-ratio) are a leading cause of CLS because the browser cannot reserve space until the file loads. Always set dimensions, and reserve space for ads, embeds, and late-loading widgets.
Do I need a perfect 100 PageSpeed score?
No. 100 is a lab vanity number. The goal is passing Core Web Vitals in the field (LCP/INP/CLS in the "good" range) for real users — a page can score 90 in Lighthouse and still pass, or score 100 and fail under real-world conditions.