Como tornar a rolagem rápida por padrão

Sahel Sharify
Sahel Sharify

Para melhorar a performance de rolagem/zoom de wheel, recomendamos que os desenvolvedores registrem listeners de eventos wheel e mousewheel como passivos, transmitindo a opção {passive: true} para addEventListener(). Registrar os listeners de eventos como passivos informa ao navegador que os listeners wheel não chamam preventDefault() e que o navegador pode rolar e aplicar zoom com segurança sem bloquear os listeners.

O problema é que, na maioria das vezes, os listeners de eventos de roda são conceitualmente passivos (não chame preventDefault()), mas não são explicitamente especificados dessa forma, exigindo que o navegador aguarde a conclusão do processamento do evento JS antes de começar a rolar/aplicar zoom, mesmo que a espera não seja necessária. No Chrome 56, corrigimos esse problema no touchstart e no touchmove, e essa mudança foi adotada depois pelo Safari e pelo Firefox. Como é possível notar no vídeo de demonstração que fizemos naquela época, o comportamento que produzia um atraso perceptível na resposta de rolagem foi mantido. No Chrome 73, aplicamos a mesma intervenção aos eventos wheel e mousewheel.

A intervenção

Nosso objetivo com essa mudança é reduzir o tempo necessário para atualizar a tela depois que o usuário começa a rolar pela roda ou pelo touchpad sem que os desenvolvedores precisem mudar o código. Nossas métricas mostram que 75% dos listeners de eventos wheel e mousewheel registrados em destinos raiz (janela, documento ou corpo) não especificam valores para a opção passiva, e mais de 98% deles não chamam preventDefault(). No Chrome 73, estamos mudando os listeners wheel e mousewheel registrados em destinos raiz (janela, documento ou corpo) para passivos por padrão. Isso significa que um listener de eventos como:

window.addEventListener("wheel", func);

se torna equivalente a:

window.addEventListener("wheel", func, {passive: true});

Além disso, chamar preventDefault() dentro do listener será ignorado com o seguinte aviso do DevTools:

[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312

Falha e orientação

Na grande maioria dos casos, nenhuma falha será observada. Somente em casos raros (menos de 0,3% das páginas de acordo com nossas métricas), a rolagem/zoom não intencional pode acontecer devido à chamada de preventDefault() ser ignorada dentro dos listeners, que são tratados como passivos por padrão. O aplicativo pode determinar se está atingindo esse objetivo, verificando se a chamada de preventDefault() teve algum efeito pela propriedade defaultPrevented. A correção para os casos afetados é relativamente fácil: transmita {passive: false} para addEventListener() para substituir o comportamento padrão e preservar o listener de eventos como bloqueio.