Sappiamo che la reattività allo scorrimento è fondamentale per il coinvolgimento dell'utente con un sito web su dispositivo mobile, ma gli ascoltatori di eventi tocco spesso causano seri problemi di prestazioni dello scorrimento. Chrome ha risolto il problema consentendo ai gestori degli eventi di tocco di essere passivi (passando l'opzione {passive: true}
a addEventListener()
) e implementando l'API eventi del cursore.
Si tratta di funzionalità eccellenti per inserire nuovi contenuti in modelli che non bloccano scorrimento, ma a volte gli sviluppatori hanno difficoltà a comprenderli e adottarli.
Riteniamo che il web debba essere veloce per impostazione predefinita senza che gli sviluppatori debbano comprendere dettagli oscuri sul comportamento del browser. In Chrome 56, per impostazione predefinita, imposteremo i listener touch su passivi nei casi in cui ciò corrisponda più spesso all'intenzione dello sviluppatore. Riteniamo che in questo modo possiamo migliorare notevolmente l'esperienza dell'utente con un impatto negativo minimo sui siti.
In rari casi, questa modifica può causare uno scorrimento involontario. Di solito questo problema può essere risolto facilmente applicando uno stile touch-action: none all'elemento in cui non deve avvenire lo scorrimento. Continua a leggere per maggiori dettagli, per sapere se il problema ti riguarda e per scoprire cosa puoi fare al riguardo.
Informazioni di sfondo: gli eventi annullabili rallentano la pagina
Se chiami
preventDefault()
negli eventi touchstart
o nel primo touchmove
, impedirai lo scorrimento.
Il problema è che nella maggior parte dei casi gli ascoltatori non chiameranno preventDefault()
, ma
il browser deve attendere il termine dell'evento per averne la certezza.
I "listener di eventi passivi" definiti dallo sviluppatore risolvono questo problema. Quando aggiungi un evento di tocco con un oggetto {passive: true}
come terzo parametro nell'handler dell'evento, stai comunicando al browser che l'ascoltatore touchstart
non chiamerà preventDefault()
e che il browser può eseguire in sicurezza lo scorrimento senza bloccarsi sull'ascoltatore. Ad esempio:
window.addEventListener("touchstart", func, {passive: true} );
The Intervention
Il nostro obiettivo principale è ridurre il tempo necessario per aggiornare il display dopo che l'utente tocca lo schermo. Per comprendere l'utilizzo di touchstart e touchmove, abbiamo aggiunto metriche per determinare la frequenza con cui si verificava il comportamento di blocco dello scorrimento.
Abbiamo esaminato la percentuale di eventi touch annullabili inviati a un target principale (finestra, documento o corpo) e abbiamo stabilito che circa l'80% di questi listener è concettualmente passivo, ma non è stato registrato come tale. Data la grandezza di questo problema, abbiamo notato una grande opportunità per migliorare lo scorrimento senza alcuna azione da parte degli sviluppatori rendendo questi eventi automaticamente "passivi".
Questo ci ha portato a definire il nostro intervento come segue: se il target di un gestore di eventi touchstart o touchmove è window
, document
o body
, per impostazione predefinita passive
viene impostato su true
. Ciò significa che codice come:
window.addEventListener("touchstart", func);
diventa equivalente a:
window.addEventListener("touchstart", func, {passive: true} );
Ora le chiamate a preventDefault()
all'interno dell'ascoltatore verranno ignorate.
Il grafico seguente mostra il tempo impiegato dal 1% di scorrimenti più elevato dal momento in cui un
utente tocca lo schermo per scorrere fino al momento in cui il display viene aggiornato. Questi dati
si riferiscono a tutti i siti web in Chrome per Android. Prima dell'attivazione dell'intervento,
l'1% degli scorrimenti richiedeva poco più di 400 ms. Ora questo tempo è stato ridotto a poco più di 250 ms
in Chrome 56 beta, ovvero una riduzione di circa il 38%. In futuro, prevediamo di impostare passive true come valore predefinito per tutti gli ascoltatori touchstart
e touchmove
, riducendo il tempo a meno di 50 ms.

Guasti e indicazioni
Nella maggior parte dei casi, non verrà rilevata alcuna interruzione. Tuttavia, quando si verificano interruzioni, il sintomo più comune è che lo scorrimento si verifica quando non lo vuoi. In rari casi, gli sviluppatori potrebbero anche notare eventi di clic imprevisti
(quando preventDefault()
non era presente in un ascoltatore touchend
).
In Chrome 56 e versioni successive, DevTools registra un avviso quando chiami preventDefault()
in un evento in cui l'intervento è attivo.
touch-passive.html:19 Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080
La tua applicazione può determinare se potrebbe verificarsi questo problema in produzione controllando se la chiamata a preventDefault
ha avuto un effetto tramite la proprietà defaultPrevented
.
Abbiamo riscontrato che la maggior parte delle pagine interessate può essere corretta in modo relativamente semplice
applicando la proprietà CSS
touch-action
se possibile. Se vuoi impedire lo scorrimento e lo zoom del browser all'interno di un elemento, applica touch-action: none
. Se hai un carousel orizzontale, ti consigliamo di applicare touch-action: pan-y pinch-zoom
in modo che l'utente possa comunque scorrere verticalmente e aumentare lo zoom come di consueto. L'applicazione corretta di "touch-action" è già necessaria su browser come Edge per computer che supportano gli eventi Pointer e non gli eventi Touch. Per Safari mobile e browser mobile meno recenti che non supportano l'azione tocco, gli ascoltatori tocco devono continuare a chiamare preventDefault
anche se verrà ignorato da Chrome.
In casi più complessi potrebbe essere necessario fare affidamento anche su uno dei seguenti elementi:
- Se il tuo listener
touchstart
chiamapreventDefault()
, assicurati che preventDefault() venga chiamato anche dai listener touchend associati per continuare a inibire la generazione di eventi di clic e di altri comportamenti predefiniti per i tocchi. - Per ultimo (e sconsigliato), passa
{passive: false}
a addEventListener() per override il comportamento predefinito. Tieni presente che dovrai rilevare se l'agente utente supporta EventListenerOptions.
Conclusione
In Chrome 56, lo scorrimento inizia molto più velocemente su molti siti web. Questo è l'unico impatto che la maggior parte degli sviluppatori noterà a seguito di questa modifica. In alcuni casi, gli sviluppatori potrebbero notare uno scorrimento involontario.
Sebbene sia ancora necessario farlo per Safari mobile, i siti web non devono basarsi sulla chiamata di preventDefault()
all'interno degli ascoltatori touchstart
e touchmove
, in quanto non è più garantito che questa operazione venga rispettata in Chrome. Gli sviluppatori devono applicare la proprietà CSS touch-action
agli elementi in cui lo scorrimento e lo zoom devono essere disattivati per avvisare il browser prima che si verifichino eventi tocco.
Per eliminare il comportamento predefinito di un tocco (ad esempio la generazione di un evento di clic), chiama preventDefault()
all'interno di un listener touchend
.