Back

Rolagem Virtual para Interfaces de Alto Desempenho

Rolagem Virtual para Interfaces de Alto Desempenho

Renderize 500.000 linhas em um navegador e sua interface provavelmente congelará, travará ou falhará. Embora os navegadores modernos possam lidar com grandes árvores DOM, o desempenho frequentemente se degrada drasticamente à medida que a contagem de nós cresce devido aos custos de layout, cálculo de estilo e memória. A rolagem virtual resolve isso renderizando apenas o que o usuário pode realmente ver — e essa única restrição muda tudo sobre como interfaces com grande volume de dados funcionam.

Pontos-Chave

  • A rolagem virtual renderiza apenas os itens visíveis na viewport (mais um pequeno buffer), mantendo a contagem de nós DOM constante independentemente do tamanho do conjunto de dados.
  • Funciona calculando os índices visíveis a partir do scrollTop, renderizando esses itens e usando elementos de preenchimento para simular a altura total rolável.
  • Alturas fixas de itens mantêm a implementação simples. Alturas dinâmicas requerem cache de medições e correção cuidadosa da posição de rolagem.
  • A busca nativa do navegador (Ctrl+F), acessibilidade e estabilidade da posição de rolagem exigem atenção extra em listas virtualizadas.
  • Existem bibliotecas maduras para React, Angular e Vue — construir do zero raramente é necessário em produção.

O Que É Rolagem Virtual (e Por Que Não É Infinite Scroll)?

Rolagem virtual (também chamada de virtualização de lista ou windowing) renderiza apenas os itens atualmente visíveis na viewport, mais um pequeno buffer acima e abaixo. À medida que o usuário rola, itens que saem da viewport são removidos do DOM e novos são inseridos em seu lugar. O conjunto de dados total nunca entra completamente no DOM.

Isso é fundamentalmente diferente do infinite scroll. O infinite scroll adiciona itens ao DOM conforme você rola — a lista continua crescendo. A rolagem virtual troca itens, mantendo a contagem de nós DOM aproximadamente constante independentemente do tamanho do conjunto de dados.

A diferença prática é significativa. Uma lista renderizada ingenuamente com 100.000 itens pode criar mais de 100.000 nós DOM na memória. Uma lista virtualizada do mesmo conjunto de dados pode manter 50–80 nós em qualquer momento.

Como Listas Virtualizadas Funcionam Conceitualmente

O mecanismo se baseia em algumas ideias diretas trabalhando juntas:

A janela da viewport. Você define uma altura fixa para o contêiner de rolagem. Isso determina quantos itens são visíveis de uma vez — chamamos de visibleCount = Math.ceil(containerHeight / itemHeight).

Cálculo de índice. À medida que o usuário rola, você lê o scrollTop para determinar qual item está no topo da área visível: startIndex = Math.floor(scrollTop / itemHeight). O índice final segue: endIndex = startIndex + visibleCount.

Ilusão de posição de rolagem. Se você renderizar apenas 50 itens, a barra de rolagem refletiria uma lista minúscula. Para simular a altura total, você coloca um elemento de preenchimento vazio acima dos itens renderizados (altura = startIndex × itemHeight) e outro abaixo (altura = espaço restante). A barra de rolagem se comporta como se o conjunto de dados completo estivesse presente.

Overscan (buffer). Renderizar apenas os itens exatamente visíveis causa um efeito de aparição brusca durante rolagem rápida. O overscan renderiza algumas linhas extras acima e abaixo da viewport — tipicamente 5–10 itens, dependendo do caso de uso — para que os itens já estejam no DOM antes de deslizarem para a visualização.

Alturas de Itens Fixas vs. Dinâmicas

A virtualização com altura fixa é direta e confiável. Cada cálculo é aritmética simples.

Alturas dinâmicas são significativamente mais difíceis. Você precisa medir cada item após a renderização e armazenar essas medições em cache, ou estimar alturas antecipadamente e corrigi-las após a medição. Ambas as abordagens adicionam complexidade e podem causar instabilidade na posição de rolagem se não forem tratadas cuidadosamente. Se seu caso de uso permitir, vale a pena projetar para alturas fixas.

Compromissos do Mundo Real a Esperar

A rolagem virtual não é gratuita. Algumas coisas quebram ou requerem trabalho extra:

  • A busca de texto do navegador (Ctrl+F) para de funcionar de forma confiável porque a maior parte do conteúdo não está no DOM. Você precisará implementar sua própria busca.
  • Acessibilidade requer atenção. Aplique role="list", role="feed" ou role="grid" ao contêiner. Você pode usar atributos como aria-setsize e aria-posinset para que tecnologias assistivas possam entender o tamanho total da lista e a posição de cada item. Mantenha o gerenciamento de foco para que a navegação por teclado não quebre quando itens forem desmontados. Um pequeno buffer de overscan também ajuda leitores de tela a detectar que existe mais conteúdo.
  • Estabilidade da posição de rolagem se torna complicada quando os dados são atualizados dinamicamente — itens adicionados ou removidos acima da posição atual de rolagem podem causar saltos bruscos.

Suporte do Ecossistema em Diferentes Frameworks

Você raramente precisa construir isso do zero em produção. Bibliotecas maduras lidam com os casos extremos:

Uma alternativa CSS que vale conhecer: content-visibility: auto permite que o navegador pule a renderização de conteúdo fora da tela sem JavaScript. Pode melhorar o desempenho de pintura em listas moderadas, mas não reduz a contagem de nós DOM e não substitui a virtualização completa em grandes conjuntos de dados.

Quando Realmente Usar

A rolagem virtual adiciona complexidade. Vale a pena quando:

  • Sua lista excede algumas centenas de itens e o desempenho de rolagem está visivelmente degradado
  • Você está construindo tabelas, visualizadores de log, feeds ou interfaces no estilo planilha
  • O uso de memória é uma restrição (dispositivos móveis, sessões de longa duração)

Para listas curtas, paginação ou lazy loading simples geralmente são mais simples e suficientes.

Conclusão

Os usuários não precisam de 100.000 nós DOM — eles precisam sentir que podem rolar por 100.000 itens. A rolagem virtual entrega essa sensação a uma fração do custo de renderização. Ao renderizar apenas a fatia visível de um conjunto de dados e trocar itens conforme o usuário rola, você mantém a contagem de nós DOM baixa, o uso de memória previsível e as taxas de quadros suaves. Os compromissos — Ctrl+F quebrado, considerações de acessibilidade, gerenciamento de posição de rolagem — são reais, mas bem compreendidos, e o ecossistema de bibliotecas em React, Angular e Vue lida com a maioria deles prontos para uso. Se sua lista é grande o suficiente para prejudicar o desempenho, a virtualização é a ferramenta mais eficaz disponível.

Perguntas Frequentes

Sim, mas requer cuidado extra. A maioria das bibliotecas de virtualização assume um layout de lista de coluna única. Para layouts baseados em grid, você precisa calcular linhas e colunas visíveis juntas, considerando itens por linha. TanStack Virtual suporta virtualização de grid nativamente. Com outras bibliotecas, você pode precisar tratar cada linha como um único item virtualizado contendo múltiplas células.

Os rastreadores de mecanismos de busca normalmente não rolam pelo conteúdo, então itens fora da renderização inicial não serão indexados. Se o SEO importa para o conteúdo da sua lista, considere saída HTML paginada ou alternativas amigáveis para rastreadores. Se você renderizar conteúdo no servidor, aplique a virtualização apenas após a hidratação no cliente.

Isso geralmente significa que seu buffer de overscan é muito pequeno ou sua renderização de itens é muito lenta. Aumente a contagem de overscan para que mais itens fora da tela sejam pré-renderizados. Também verifique se seus itens de lista acionam recálculos de layout caros ou carregam imagens sincronamente. Simplificar componentes de itens e usar conteúdo de placeholder para imagens pode reduzir significativamente os quadros em branco.

Sim. Antes da navegação, salve o valor atual de scrollTop e o startIndex correspondente no estado ou session storage. Quando o usuário retornar, restaure a posição do contêiner de rolagem para o valor salvo de scrollTop. A maioria das bibliotecas de virtualização expõe um método scrollToIndex ou scrollToOffset que torna isso direto de implementar na remontagem.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay