Back

ResizeObserver vs Window Resize: Quando Usar Cada Um

ResizeObserver vs Window Resize: Quando Usar Cada Um

Você está construindo um componente de gráfico que precisa ser redesenhado quando seu contêiner encolhe. Você recorre ao window.addEventListener('resize', ...) e funciona na maioria das vezes—até que o painel redimensiona devido ao colapso de uma barra lateral, e nada dispara. Esse é o problema central que este artigo aborda.

Principais Conclusões

  • O evento resize do window só dispara quando o viewport do navegador muda de tamanho. Ele não sabe nada sobre elementos DOM individuais.
  • ResizeObserver observa elementos específicos e dispara sempre que suas dimensões mudam, independentemente da causa.
  • Fazer polling dos tamanhos de elementos após um redimensionamento do viewport é frágil—perde mudanças de alternâncias CSS, conteúdo dinâmico, carregamento de fontes e muito mais.
  • Para estilização baseada em contêiner sem JavaScript, CSS container queries são a ferramenta preferida.

O Que Cada API Realmente Observa

O evento resize do window dispara quando o viewport do navegador muda de tamanho. Esse é todo o seu escopo. Ele não sabe nada sobre elementos DOM individuais.

ResizeObserver observa elementos específicos e dispara sempre que suas dimensões mudam—independentemente do que causou. Um redimensionamento do viewport, uma inserção no DOM, uma alternância de classe CSS, um reflow de flexbox pai—todos esses eventos disparam o observador se o tamanho do elemento mudar.

Esta é a distinção fundamental. Eles observam coisas diferentes e geralmente são escolhidos para trabalhos diferentes.

Quando Usar o Evento Window Resize

O evento resize do window é a ferramenta certa quando sua lógica genuinamente depende das dimensões do viewport, não do tamanho de nenhum elemento em particular:

  • Alternar um layout de navegação mobile em um breakpoint do viewport
  • Redimensionar um canvas de página inteira ou contexto WebGL para window.innerWidth / window.innerHeight
  • Ajustar o estado de layout global que depende do espaço disponível na tela
window.addEventListener('resize', () => {
  canvas.width = window.innerWidth
  canvas.height = window.innerHeight
  render()
})

Para respostas puramente visuais e orientadas por CSS ao tamanho do viewport, prefira media queries em vez de JavaScript.

Quando Usar ResizeObserver

Os casos de uso do ResizeObserver se concentram em comportamento no nível do componente que deve responder ao tamanho renderizado real de um elemento:

  • Um gráfico que recalcula escalas de eixos quando a largura de seu contêiner muda
  • Um editor de texto que ajusta o layout da barra de ferramentas com base no espaço disponível
  • Um painel redimensionável ou widget de painel dividido
  • Qualquer widget incorporado que não controla seu próprio contêiner
const ro = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const { inlineSize, blockSize } = entry.contentBoxSize[0]
    chart.resize(inlineSize, blockSize)
  }
})

ro.observe(document.querySelector('.chart-container'))

Lendo a Forma Moderna da API

A API atual do ResizeObserver expõe arrays contentBoxSize e borderBoxSize em cada entrada—cada um contendo inlineSize (largura em modos de escrita horizontal) e blockSize (altura). A propriedade mais antiga contentRect ainda funciona, mas existe principalmente para compatibilidade retroativa. Prefira contentBoxSize[0] em código novo.

Por Que Não Simplesmente Fazer Polling Após um Window Resize?

Um padrão comum—escutar o evento resize do window e então chamar getBoundingClientRect() em elementos—é frágil. Ele perde mudanças de tamanho que não têm nada a ver com o viewport: carregamento de conteúdo dinâmico, classes CSS alternadas, filhos injetados, carregamento de fontes. ResizeObserver captura todos esses casos. Polling após um redimensionamento do viewport não captura.

Performance e Loops de Feedback

Os callbacks do ResizeObserver são executados após o layout e antes da pintura, o que significa que leituras do DOM dentro do callback refletem o layout atual sem forçar um reflow. Isso é estruturalmente mais seguro do que ler propriedades de layout dentro de um manipulador de evento resize.

Uma pegadinha: se você modificar o tamanho de um elemento observado dentro de seu próprio callback, você dispara outra observação. ResizeObserver lida com isso processando observações em profundidades progressivamente maiores do DOM dentro do mesmo frame e eventualmente reportando um erro se o ciclo não se resolver—prevenindo loops infinitos. Você ainda deve ser deliberado sobre o que escreve dentro do callback.

A vantagem de performance do ResizeObserver se torna significativa quando seu callback toca o layout ou quando mudanças de tamanho de elemento ocorrem independentemente do redimensionamento do viewport.

A Alternativa das CSS Container Queries

Se seu objetivo é estilizar um elemento com base no tamanho de seu contêiner, CSS container queries são a ferramenta certa—sem necessidade de JavaScript. Reserve o ResizeObserver para casos onde lógica de runtime, não estilização, deve responder a mudanças de tamanho.

CenárioMelhor Ferramenta
Mudanças de layout em todo o viewportEvento resize do window
Dimensões de elemento dirigem lógica JSResizeObserver
Apenas estilização baseada em contêinerCSS container queries

Conclusão

Use o evento resize do window quando você se importa com o viewport. Use ResizeObserver quando você se importa com um elemento. Use CSS container queries quando você só precisa mudar estilos. Essas três ferramentas cobrem todo o espaço de comportamento responsivo—escolha a que corresponde ao que você está realmente medindo.

Perguntas Frequentes

ResizeObserver dispara quando as dimensões de um elemento mudam, então colapsar um elemento para largura ou altura zero irá dispará-lo. No entanto, ele não dispara para mudanças de visibility ou opacity que deixam as dimensões intactas. Para detecção de visibilidade verdadeira, use IntersectionObserver em vez disso.

O observador automaticamente para de rastrear um elemento assim que ele é coletado pelo garbage collector. No entanto, chamar explicitamente unobserve ou disconnect é uma boa prática, especialmente em aplicações de página única ou componentes de framework com ciclos de vida de montagem e desmontagem, para evitar referências obsoletas e callbacks inesperados.

Sim. ResizeObserver tem amplo suporte no Chrome, Firefox, Safari e Edge. Se você precisa suportar navegadores mais antigos, um polyfill está disponível, embora ele dependa internamente de polling e mutation observers, então não corresponderá à performance nativa.

Geralmente não para atualizações leves de UI. ResizeObserver já agrupa notificações eficientemente dentro do pipeline de renderização. No entanto, se seu callback dispara trabalho downstream caro, como requisições de rede ou computação pesada, faça debounce desse trabalho específico em vez do callback inteiro.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue 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