A rolagem na Web precisa ser suave e responsiva. A execução de tarefas pesadas, como recálculos de layout, rastreamento de beacons de dados de análise ou atualizações dinâmicas do DOM, durante a rolagem pode saturar a linha de execução principal, resultando em queda de frames e thrashing de layout.
No passado, os desenvolvedores dependiam do debounce do evento scroll usando setTimeout() para adivinhar quando uma rolagem terminava. No entanto, essas funções de debounce são notoriamente não confiáveis. Eles podem ser acionados enquanto o usuário ainda está rolando a tela.
O evento scrollend oferece uma solução altamente confiável e focada no desempenho. O navegador aciona um evento scrollend exatamente quando uma rolagem é interrompida, todas as transições são concluídas e um gesto de toque é liberado.
Como implementar
Para implementar um padrão de trabalho adiado:
- Configurar um contêiner rolável: crie um contêiner com
overflow: autoouoverflow: scroll. - Detectar eventos
scroll: use esse listener apenas para métricas dinâmicas básicas ou estilo de layout informativo. Não execute trabalhos pesados aqui. - Detectar eventos
scrollend: registre um callbackscrollendno contêiner de rolagem ou no próprio documento. - Executar trabalho caro no callback: é aqui que é seguro buscar conteúdo dinâmico ou acionar layouts DOM abrangentes.
Exemplo de código
.scroll-container {
height: 300px;
overflow-y: auto;
}
const scroller = document.querySelector('.scroll-container');
// 1. Informative feedback during scroll
scroller.addEventListener('scroll', () => {
// Avoid dynamic heavier data updates here
console.log('Scrolling dynamically... updates deferred');
});
// 2. Safe callback when scrolling rests
scroller.addEventListener('scrollend', () => {
// Run layout recalculations or analytical beacons updates here
const currentVisibleSection = findMostVisibleSection(scroller);
fetchAdditionalData(currentVisibleSection);
});
Implementação estratégica e práticas recomendadas
- USE
scrollendem vez de eventosscrollcom debounce ao disparar beacons de dados de layout ou buscar um novo layout de conteúdo dinamicamente. - RECOMENDAMOS considerar o uso de interações de ajuste
scrollSnapChangeouscrollSnapChangingse você estiver criando carrosséis ou slides de galerias de depoimentos. - NÃO agrupe atualizações dinâmicas dependentes de layout em callbacks de rolagem visual dinâmica.
- CONSIDERE que o zoom e a rolagem da janela de visualização visual acionam o evento
scrollendcorretamente.
Estratégia de fallback
Para navegadores incompatíveis, use um evento scroll com setTimeout para enviar um evento scrollend personalizado.
function initializeDemo() {
const scroller = document.querySelector('#scroller');
scroller.addEventListener('scrollend', () => {
// Safe execution
});
}
if ('onscrollend' in window) {
initializeDemo();
} else {
initializeDemo();
const scroller = document.querySelector('#scroller');
scroller.addEventListener('scroll', () => {
clearTimeout(window.scrollendtimer);
window.scrollendtimer = setTimeout(() => {
scroller.dispatchEvent(new CustomEvent('scrollend'));
}, 100);
});
}