Adiar o trabalho até o fim da rolagem

Recursos da Web: scrollend

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:

  1. Configurar um contêiner rolável: crie um contêiner com overflow: auto ou overflow: scroll.
  2. 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.
  3. Detectar eventos scrollend: registre um callback scrollend no contêiner de rolagem ou no próprio documento.
  4. 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 scrollend em vez de eventos scroll com 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 scrollSnapChange ou scrollSnapChanging se 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 scrollend corretamente.

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);
  });
}