Referência rápida

Folha de Cola Layout Thrashing e Forced Reflow

Guia de referência completo sobre layout thrashing e forced reflow: propriedades de elementos DOM, eventos de mouse, métodos window e chamadas jQuery que degradam a renderização.

· Publicado

Layout thrashing (também conhecido como layout síncrono forçado ou forced reflow) ocorre quando o JavaScript alterna repetidamente entre escrever no DOM e ler propriedades de layout, forçando o navegador a recalcular o layout de forma síncrona.

Gatilhos de Invalidação de Layout

As propriedades e métodos DOM abaixo forçam o recálculo síncrono da geometria computada sempre que o layout tiver sido invalidado por alterações anteriores no DOM.

Propriedades e Métodos de Elemento

Geometria e Dimensões da Caixa

  • clientHeight, clientWidth
  • clientLeft, clientTop
  • offsetHeight, offsetWidth
  • offsetLeft, offsetTop
  • offsetParent
  • scrollHeight, scrollWidth
  • scrollLeft, scrollTop

Consultas de Caixa Delimitadora

  • getBoundingClientRect()
  • getClientRects()

Ações de Rolagem

  • scrollIntoView()
  • scrollIntoViewIfNeeded()
  • scrollByLines()
  • scrollByPages()

Texto e Foco

  • innerText
  • outerText
  • focus() (força anel de foco e ajustes de rolagem)

Propriedades de Evento de Mouse

Consultar coordenadas específicas em uma instância de MouseEvent pode acionar o cálculo de layout em alguns motores de navegador:

  • layerX, layerY
  • offsetX, offsetY

Métodos e Propriedades de Window

  • window.getComputedStyle() (ao consultar valores dependentes de layout como largura, altura, margem ou transform)
  • window.scrollBy()
  • window.scrollTo()
  • window.scrollX, window.scrollY

Frame, Documento e Imagem

  • Consultar width ou height em uma imagem antes que o layout estabilize
  • Acessar document.body.scrollHeight

Operações com jQuery

Muitos métodos auxiliares do jQuery leem valores de layout computados internamente:

// Dispara reflow
$(elem).offset();
$(elem).offsetParent();
$(elem).position();
$(elem).scrollLeft();
$(elem).scrollTop();
$(elem).css('width');  // Qualquer cálculo de estilo dependente do layout
$(elem).text();

// Pseudoseletores que inspecionam visibilidade geométrica
$(':hidden');
$(':visible');
$(':contains');

Boas Práticas para Evitar Layout Thrashing

1. Agrupar Leituras e Escritas em Lote

Sempre execute primeiro todas as medições do DOM e depois agrupe todas as alterações no DOM.

// RUIM: Intercalar leitura e escrita força layout a cada iteração
elements.forEach((el) => {
  const width = el.clientWidth; // LEITURA (força layout)
  el.style.width = width * 2 + 'px'; // ESCRITA (invalida layout)
});

// BOM: Leituras em lote e depois escritas em lote
const widths = elements.map((el) => el.clientWidth); // LEITURA EM LOTE
elements.forEach((el, index) => {
  el.style.width = widths[index] * 2 + 'px'; // ESCRITA EM LOTE
});

2. Usar requestAnimationFrame

Agende alterações de estilo para o próximo quadro de animação para que o navegador otimize o ciclo de renderização:

const height = element.clientHeight; // Ler durante a fase atual

window.requestAnimationFrame(() => {
  element.style.height = height + 50 + 'px'; // Escrever no próximo quadro
});

3. Usar CSS Transforms e Opacity

Prefira animar propriedades CSS tratadas na thread de composição (transform, opacity) em vez de propriedades de layout (top, left, width, height).


Referências

Temas relacionados