Core Web Vitals: guida pratica a LCP, CLS e INP

I Core Web Vitals sono tre metriche con cui Google quantifica l’esperienza utente sulle pagine web. Sono un fattore di ranking dal 2021, ma dal marzo 2024 c’è stato un cambio importante: FID (First Input Delay) è stato sostituito da INP (Interaction to Next Paint), metrica molto più severa e realistica. Molte guide online sono rimaste indietro e citano ancora FID — se le trovi, sappi che sono datate.

Questo articolo copre le tre metriche attuali, le soglie ufficiali, gli strumenti di misurazione e — punto che di solito manca — le cause tecniche reali che le peggiorano e come intervenire.

Le tre metriche e le soglie

Dati ufficiali Google (web.dev/vitals):

Metrica Misura Buono Da migliorare Scarso
LCP (Largest Contentful Paint) Tempo di rendering dell’elemento visibile più grande ≤ 2,5 s 2,5 – 4,0 s > 4,0 s
CLS (Cumulative Layout Shift) Stabilità visiva (quanto “saltano” gli elementi mentre carica) ≤ 0,1 0,1 – 0,25 > 0,25
INP (Interaction to Next Paint) Reattività alle interazioni utente (click, tap, tastiera) ≤ 200 ms 200 – 500 ms > 500 ms

Una pagina è considerata “Good” da Google se tutte e tre le metriche sono nella fascia verde al 75° percentile del traffico reale degli ultimi 28 giorni. “Tutte e tre” è la parte che viene dimenticata: un LCP di 1.8s non ti salva se l’INP è a 400ms.

Dove si misurano: dati di laboratorio vs dati di campo

Distinzione fondamentale che genera confusione costante:

Dati di laboratorio (lab data): un browser simulato esegue la tua pagina in condizioni controllate. Strumenti: Lighthouse, PageSpeed Insights (sezione “Analysis”), DevTools. Velocissimi, ripetibili, ma non sono quelli che Google usa per il ranking.

Dati di campo (field data, CrUX): metriche raccolte da Chrome reale sugli utenti reali che visitano il tuo sito, anonimizzate e aggregate nel Chrome User Experience Report. Sono quelli che contano. Strumenti:

  • PageSpeed Insights (sezione “Discover what your real users are experiencing”)
  • Google Search Console → Esperienza → Segnali web essenziali
  • CrUX Dashboard su Google BigQuery
  • RUM proprietario (Real User Monitoring) tramite la web-vitals library di Google

Regola operativa: Lighthouse serve a trovare cosa peggiora i Vitals. CrUX ti dice se per gli utenti veri la pagina passa o no. Senza traffico sufficiente (tipicamente ~1000 visite/mese), una URL non ha dati CrUX e Google usa dati di origine (sitewide) come fallback.

LCP: il dettaglio che manca in tutte le guide

LCP misura il tempo dal momento in cui l’utente richiede la pagina fino a quando l’elemento visibile più grande del viewport iniziale è stato renderizzato. Di solito è:

  • L’hero image / banner principale (e-commerce, landing)
  • Il titolo H1 se non c’è immagine grande (blog, articoli)
  • Un video poster
  • Raramente: un blocco di testo molto grande

La composizione di LCP (ecco dove intervenire)

Google scompone LCP in 4 sotto-tempi:

LCP = TTFB + Resource Load Delay + Resource Load Duration + Element Render Delay
Sotto-metrica Cos’è Come si migliora
TTFB (Time to First Byte) Tempo server lato backend + rete CDN, caching, hosting migliore, ottimizzare query DB
Resource Load Delay Tempo tra inizio pagina e inizio download risorsa LCP fetchpriority="high" sull’immagine LCP, preload, eliminare lazy loading sull’hero
Resource Load Duration Tempo effettivo di download Formato immagine (WebP/AVIF), compressione, dimensioni corrette, CDN
Element Render Delay Tempo tra risorsa scaricata e rendering Ridurre JS bloccante, eliminare render-blocking CSS

Il singolo intervento con il miglior rapporto sforzo/risultato per migliorare LCP è quasi sempre fetchpriority="high" sull’immagine hero, introdotto da Chrome nel 2023:

<img
  src="/hero.webp"
  alt="..."
  width="1200"
  height="600"
  fetchpriority="high"
>

Questo dice al browser di scaricare quell’immagine prima di CSS e JS che normalmente avrebbero priorità, riducendo il Resource Load Delay di centinaia di millisecondi.

Errore frequentissimo: lazy loading dell’immagine LCP. loading="lazy" sull’hero fa esplodere l’LCP di 1-2 secondi. L’hero image non va mai in lazy loading.

CLS: cosa lo rompe davvero

CLS misura la somma degli spostamenti inaspettati del layout durante la vita della pagina (finestra di 5 secondi). Un CLS di 0.25 significa che qualcosa è “saltato” in modo fastidioso durante il caricamento.

Cause in ordine di frequenza reale

  1. Immagini senza attributi width e height. Quando un’immagine carica, se il browser non conosce le proporzioni, deve “allargare” lo spazio al momento del download — tutto il contenuto sottostante salta. Fix:
    <img src="..." width="800" height="600" alt="...">
    

    Oppure CSS aspect-ratio: 800/600. Funziona anche con immagini responsive.

  2. Ads, embed, iframe senza dimensioni riservate. Google AdSense, video YouTube, widget social, chat widget. Qualsiasi cosa si carichi in asincrono e occupi spazio non dichiarato. Riserva lo spazio con un contenitore di dimensioni fisse.
  3. Web fonts che causano FOUT/FOIT. Il browser mostra prima il fallback (system font), poi quando il font custom è pronto sostituisce e tutto si riposiziona. Fix:
    • font-display: optional nel @font-face (scarica se fa in tempo, altrimenti usa fallback)
    • size-adjust in CSS per matching delle metriche tra fallback e custom font
    • Preload dei font critici: <link rel="preload" as="font" ...>
  4. Contenuto inserito dinamicamente sopra contenuto esistente. Banner cookie che appare in cima alla pagina dopo 200ms, notifica “iscriviti alla newsletter”, toolbar di traduzione. Tutto quello che appare sopra il fold dopo il primo render causa CLS. Soluzione: se deve apparire, fallo come overlay posizionato (che non sposta il flusso) o riserva lo spazio fin dall’inizio.
  5. Animazioni non-compositor. Animare width, height, top, left causa reflow dell’intera pagina. Usa solo transform e opacity, che il browser può animare sul compositor thread senza ricalcolare il layout.

INP: la metrica che ha ucciso i siti pesanti di JavaScript

INP misura la latenza dell’interazione più lenta durante la visita: dal momento in cui l’utente clicca/tocca/digita, al momento in cui il prossimo frame viene disegnato dopo che il browser ha processato l’evento.

Perché è più severo di FID: FID misurava solo la prima interazione e solo il delay input (il tempo prima che l’handler iniziasse). INP misura il tempo totale — handler + rendering — di tutte le interazioni della visita, e prende il valore peggiore (con correzione per outlier su visite molto lunghe).

Siti single-page con framework pesanti (React, Vue, Angular) che prima passavano FID con FID < 100ms ora falliscono INP con valori di 400-800ms. È un problema reale.

Cause principali di INP alto

  1. JavaScript di terze parti pesante. Tag manager che carica 15 script, tracking di analytics multipli, chatbot, personalizzazione A/B, heatmap (Hotjar, Clarity). Ogni task sopra i 50ms sul main thread blocca le interazioni.
  2. Event handler che fanno troppo lavoro sincrono. Un onClick che esegue 300ms di calcoli prima di aggiornare il DOM blocca tutto per 300ms. Fix: spezzare il lavoro con scheduler.yield() o requestIdleCallback, o spostare calcoli pesanti in Web Workers.
  3. Re-render massicci del framework. In React, uno state update al livello più alto può causare il re-render di tutto l’albero. Fix: memoization (useMemo, React.memo), virtualizzazione di liste lunghe, code splitting aggressivo.
  4. DOM enormi. Pagine con 3000+ elementi DOM sono naturalmente lente a reagire. Google consiglia < 1500 nodi, < 32 livelli di annidamento, nessun elemento con > 60 figli.

Come diagnosticare INP

Lighthouse non è sufficiente per INP — è una metrica di field data. Strumenti utili:

  • Chrome DevTools > Performance panel > Interactions track: mostra esattamente quali interazioni sono lente e dove si blocca il main thread
  • web-vitals library con onINP() per raccogliere dati reali
  • PageSpeed Insights → Diagnose performance issues > Longest Interaction

Comando base per test live su Chrome:

import { onINP } from 'web-vitals';
onINP((metric) => {
  console.log('INP:', metric.value, 'ms', metric);
});

Strumenti: quale usare quando

Obiettivo Strumento Perché
Diagnosi singola pagina Lighthouse in DevTools Veloce, ripetibile, suggerimenti automatici
Capire cosa vedono gli utenti reali PageSpeed Insights (sezione field) Dati CrUX ufficiali
Monitoraggio sitewide Search Console > Esperienza Dashboard Google ufficiale per tutto il sito
Profilazione dettagliata DevTools > Performance panel Flame chart completo, per debug approfondito
Real User Monitoring in produzione web-vitals library + proprio backend Dati continui sul tuo traffico, segmentabili per URL/device/browser
Confronto con competitor CrUX Dashboard (BigQuery) Dati CrUX aggregati pubblici per qualsiasi dominio

Gerarchia degli interventi

Per un sito mediamente ottimizzato, l’ordine di priorità a maggior ROI è:

  1. CDN davanti al sito (se non ce l’hai già). Riduce TTFB → migliora LCP globalmente.
  2. Compressione e formati immagine moderni (WebP/AVIF) + dimensioni corrette. Impatto forte su LCP.
  3. fetchpriority="high" sull’hero image. Guadagno tipico 200-500ms su LCP.
  4. Dimensioni esplicite su tutte le immagini e iframe. Azzera gran parte del CLS.
  5. Audit script di terze parti (tag manager, analytics, widget): rimuovi quelli che nessuno usa, carica in defer quelli non critici. Grande impatto su INP.
  6. Font: font-display: optional o swap + preload dei critici.
  7. Code splitting e lazy loading di route non critiche (per SPA).

Tutto il resto (micro-ottimizzazioni CSS, tree shaking avanzato, service worker) è secondario finché non hai sistemato questi sette punti.

Cosa cambia nel 2026

Google ha annunciato che sta valutando l’aggiunta di nuove metriche ai Core Web Vitals:

  • Responsiveness extensions: metriche più granulari sulla reattività percepita
  • Scroll performance: quanto è fluido lo scroll
  • Smooth animations: qualità delle animazioni in termini di frame drop

Nessuna di queste è ancora ufficialmente un ranking factor al momento della scrittura. Tienile d’occhio tramite il Chrome blog e web.dev.

Takeaway

  • I Core Web Vitals contano al 75° percentile del traffico reale, non in condizioni di laboratorio
  • INP ha sostituito FID nel marzo 2024: se la tua guida di riferimento parla di FID, è datata
  • LCP si migliora quasi sempre con: CDN + immagini ottimizzate + fetchpriority sull’hero
  • CLS si risolve nell’80% dei casi dichiarando dimensioni a immagini e iframe
  • INP è il vero banco di prova dei siti pesanti di JavaScript: se usi React/Vue/Angular su un sito pubblico, auditalo subito
  • Passare i Vitals è un requisito, non un vantaggio competitivo: lo fanno tutti i siti seri, non ti distingue

Torna in alto