Como tornar a rolagem rápida por padrão

Sahel Sharify
Sahel Sharify

Para melhorar o desempenho de rolagem/zoom do wheel, recomendamos que os desenvolvedores registrem listeners de eventos wheel e mousewheel como passivos transmitindo a opção {passive: true} para addEventListener(). O registro dos listeners de eventos como passivos informa ao navegador que os listeners de roda não vão chamar preventDefault(), e o navegador pode rolar e fazer 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 chamam preventDefault()), mas não são especificados explicitamente como tais, exigindo que o navegador aguarde a conclusão do processamento de eventos do JS antes de começar a rolar/fazer zoom, mesmo que a espera não seja necessária. No Chrome 56, resolvemos esse problema para touchstart e touchmove, e essa mudança foi adotada mais tarde pelo Safari e pelo Firefox. Como você pode ver no vídeo de demonstração que fizemos na época, deixar o comportamento como ele era produziu um atraso perceptível na resposta de rolagem. Agora, 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 a roda ou o 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 nenhum valor para a opção passiva, e mais de 98% desses listeners não chamam preventDefault(). No Chrome 73, estamos mudando os listeners wheel e mousewheel registrados em destinos raiz (janela, documento ou corpo) para serem passivos por padrão. Isso significa que um listener de eventos como:

window.addEventListener("wheel", func);

fica equivalente a:

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

E a chamada de preventDefault() dentro do listener será ignorada 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

Interrupção e orientação

Na grande maioria dos casos, não há quebra. Somente em casos raros (menos de 0,3% das páginas de acordo com nossas métricas), a rolagem/zoom não intencionais podem acontecer devido à chamada preventDefault() ser ignorada dentro dos listeners que são tratados como passivos por padrão. Seu app pode determinar se ele pode estar atingindo esse ponto verificando se a chamada 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.