Referencia rápida

Hoja de referencia de Layout Thrashing y Reflow forzado

Guía completa sobre layout thrashing y forced reflow: propiedades DOM, eventos de ratón, métodos de window y disparadores jQuery que degradan el renderizado.

· Publicado

El layout thrashing (también llamado diseño síncrono forzado o forced reflow) ocurre cuando JavaScript alterna repetidamente entre escribir en el DOM y leer propiedades geométricas, obligando al navegador a recalcular el diseño de forma síncrona.

Disparadores de invalidación de layout

Las siguientes propiedades y métodos del DOM fuerzan el recálculo síncrono de la geometría siempre que el diseño haya sido invalidado por mutaciones previas.

Propiedades y métodos de elementos

Geometría y dimensiones de caja

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

Consultas de cuadros delimitadores

  • getBoundingClientRect()
  • getClientRects()

Acciones de desplazamiento

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

Texto y foco

  • innerText
  • outerText
  • focus() (fuerza anillo de foco y ajustes de desplazamiento)

Propiedades de eventos de ratón

Consultar ciertas coordenadas en una instancia MouseEvent puede desencadenar cálculos de diseño en algunos motores:

  • layerX, layerY
  • offsetX, offsetY

Métodos y propiedades de Window

  • window.getComputedStyle() (al consultar propiedades dependientes del diseño como ancho, alto o márgenes)
  • window.scrollBy()
  • window.scrollTo()
  • window.scrollX, window.scrollY

Frame, documento e imagen

  • Consultar width o height de una imagen antes de estabilizarse el diseño
  • Acceder a document.body.scrollHeight

Operaciones con jQuery

Muchos métodos auxiliares de jQuery leen internamente valores de diseño calculados:

// Desencadena reflow
$(elem).offset();
$(elem).offsetParent();
$(elem).position();
$(elem).scrollLeft();
$(elem).scrollTop();
$(elem).css('width');  // Cualquier cálculo de estilo dependiente del diseño
$(elem).text();

// Pseudoselectores que inspeccionan visibilidad geométrica
$(':hidden');
$(':visible');
$(':contains');

Buenas prácticas para evitar el Layout Thrashing

1. Agrupar lecturas y escrituras por lotes

Realiza siempre todas las mediciones del DOM primero y luego aplica las modificaciones juntas.

// MAL: Intercalar lectura y escritura fuerza recalcular el layout en cada iteración
elements.forEach((el) => {
  const width = el.clientWidth; // LECTURA (fuerza layout)
  el.style.width = width * 2 + 'px'; // ESCRITURA (invalida layout)
});

// BIEN: Lecturas por lotes y luego escrituras por lotes
const widths = elements.map((el) => el.clientWidth); // LECTURA POR LOTES
elements.forEach((el, index) => {
  el.style.width = widths[index] * 2 + 'px'; // ESCRITURA POR LOTES
});

2. Usar requestAnimationFrame

Programa escrituras de estilo en el siguiente fotograma para que el navegador optimice el ciclo de pintado:

const height = element.clientHeight; // Leer durante la fase actual

window.requestAnimationFrame(() => {
  element.style.height = height + 50 + 'px'; // Escribir en el siguiente fotograma
});

3. Usar transformaciones CSS y opacidad

Prioriza animar propiedades CSS gestionadas por el compositor (transform, opacity) en lugar de propiedades de diseño (top, left, width, height).


Referencias

Temas relacionados