L'Interaction to Next Paint ha sostituito il First Input Delay tra i Core Web Vitals nel marzo 2024. La differenza è sostanziale: il vecchio indicatore guardava solo il ritardo della prima interazione, mentre l'INP osserva tutte le interazioni della visita (clic, tocchi, pressioni di tasti) e riporta un valore vicino alla peggiore. Un INP fino a 200 millisecondi è considerato buono, oltre 500 è scarso. Chi ha un sito con molte interazioni, come un configuratore o un'area riservata, se ne accorge subito.
Le tre parti di un'interazione
Ogni interazione misurata dall'INP si compone di tre tempi:
- ritardo di input: il tempo tra il gesto dell'utente e l'avvio dei gestori di evento. È lungo quando il main thread è già occupato da un altro task;
- tempo di elaborazione: quanto impiegano i gestori
click,keydown,pointerupe simili a terminare; - ritardo di presentazione: il tempo che serve al browser per ricalcolare stili, layout e disegnare il fotogramma successivo.
L'utente percepisce la somma: tocca un pulsante e per un istante non succede nulla. Ognuna delle tre parti ha cause e rimedi diversi.
Il nemico principale: i task lunghi
Il browser esegue JavaScript, calcolo degli stili, layout e disegno su un unico thread principale. Un task che dura più di 50 millisecondi è considerato "lungo" perché, mentre è in corso, nessun'altra cosa può accadere. Se l'utente tocca lo schermo durante un task da 300 millisecondi, quel tempo diventa ritardo di input.
Le fonti tipiche di task lunghi sono l'avvio di framework pesanti, script di terze parti che si eseguono tutti insieme, la manipolazione di elenchi con migliaia di elementi e gestori di evento che fanno troppo lavoro in una sola volta.
Restituire il controllo al browser
La tecnica centrale si chiama yielding: spezzare il lavoro in blocchi e, tra un blocco e l'altro, lasciare che il browser gestisca input e disegno. Un approccio diffuso e compatibile usa una promessa con setTimeout:
function cediIlPasso() {
if ('scheduler' in window && 'yield' in scheduler) {
return scheduler.yield();
}
return new Promise(r => setTimeout(r, 0));
}
async function elaboraRighe(righe) {
for (let i = 0; i < righe.length; i++) {
aggiornaRiga(righe[i]);
if (i % 50 === 0) await cediIlPasso();
}
}
scheduler.yield() è disponibile nei browser basati su Chromium e ha il vantaggio di riprendere il lavoro con priorità più alta rispetto a un semplice timeout; il fallback garantisce il funzionamento ovunque.
Prima il feedback, poi il resto
Un principio pratico: nel gestore di evento fai solo ciò che serve per mostrare all'utente che l'azione è stata ricevuta, poi rimanda il resto. Se un clic su «Aggiungi al carrello» deve aggiornare il contatore, inviare un evento di analytics, salvare nel localStorage e ricalcolare i suggerimenti, solo il primo punto è urgente.
pulsante.addEventListener('click', async () => {
contatore.textContent = ++totale; // visibile subito
await cediIlPasso();
inviaAnalytics('aggiunta');
salvaCarrello();
ricalcolaSuggerimenti();
});
Il fotogramma con il contatore aggiornato viene disegnato prima che parta il lavoro secondario, e l'INP misura proprio quel fotogramma.
Ridurre il ritardo di presentazione
Anche con gestori veloci, l'interazione può risultare lenta se il browser deve ricalcolare un layout enorme. Le cause più comuni:
- un DOM con decine di migliaia di nodi, dove anche un piccolo cambiamento di classe sul
bodycostringe a rivalutare molti selettori; - letture e scritture di layout alternate (leggere
offsetHeight, cambiare uno stile, rileggere), che forzano più ricalcoli nello stesso fotogramma; - inserimento di grandi blocchi di HTML con
innerHTMLin risposta al clic.
Mantenere il DOM contenuto, raggruppare le letture prima delle scritture e aggiornare solo la porzione necessaria sono interventi che si vedono subito.
Come trovare le interazioni lente
In laboratorio, il pannello Performance di DevTools mostra la traccia delle interazioni con la durata delle tre parti; conviene attivare il rallentamento della CPU per simulare un telefono di fascia media, perché su un portatile potente quasi tutto sembra veloce. Sul campo, la libreria web-vitals con attribuzione indica l'elemento su cui è avvenuta l'interazione peggiore e il tipo di evento: raccogliendo questi dati si scopre, per esempio, che l'INP cattivo dipende tutto dal menu a tendina dei filtri di una sola pagina.
Errori comuni
- Ottimizzare solo il caricamento iniziale e dimenticare che l'INP si misura per tutta la visita.
- Spostare il lavoro in un
setTimeoutlungo, che rimanda il problema senza risolverlo se poi il task resta monolitico. - Testare solo su desktop: la differenza di potenza di calcolo tra dispositivi rende l'INP una metrica soprattutto mobile.
In sintesi
- L'INP misura la latenza di tutte le interazioni e riporta un valore vicino alla peggiore; buono fino a 200 ms.
- È composto da ritardo di input, tempo di elaborazione e ritardo di presentazione.
- I task lunghi sul main thread sono la causa principale: spezzali e cedi il passo al browser.
- Mostra subito il feedback visivo e rimanda il lavoro secondario.
- Misura su dispositivi lenti o con CPU rallentata e raccogli dati reali con attribuzione.