DOM performance: evita reflows y trabajo innecesario

Aprende a reducir coste de renderizado agrupando cambios y minimizando lecturas/escrituras conflictivas del layout.

Rendimiento DOM no va de micro-trucos: va de no forzar trabajo extra al navegador.

El mayor problema suele ser alternar lecturas y escrituras de layout en bucles.

Agrupar cambios reduce reflows y hace la UI más estable.

Primero corrige patrones malos; luego optimiza detalles.

  • Leer medidas y escribir estilos en cada iteración dispara coste.
  • Cuando consultas `offsetHeight/getBoundingClientRect` y justo después cambias estilos repetidamente, el navegador recalcula layout muchas veces.
  • Ese patrón degrada rendimiento sobre todo en listas largas o animaciones.
  • Primero mide, luego aplica cambios.
  • Evita `innerHTML +=` dentro de bucles.

Qué es el layout thrashing

Leer medidas y escribir estilos en cada iteración dispara coste.

Cuando consultas `offsetHeight/getBoundingClientRect` y justo después cambias estilos repetidamente, el navegador recalcula layout muchas veces.

Ese patrón degrada rendimiento sobre todo en listas largas o animaciones.

Batch updates: agrupar lecturas y escrituras

Primero mide, luego aplica cambios.

  • Evita `innerHTML +=` dentro de bucles.
  • Si creas muchos nodos, usa `DocumentFragment`.
  • Usa clases CSS en lote en lugar de estilos inline por nodo.

Fragmentos y requestAnimationFrame

Dos herramientas simples para UIs más fluidas.

`DocumentFragment` permite montar estructura en memoria y hacer un solo append al DOM.

`requestAnimationFrame` coordina cambios visuales con el ciclo de pintado del navegador.

Reutilizar nodos cuando cambia el layout

No siempre hace falta destruir y reconstruir toda la interfaz.

En interfaces que responden al tamaño de pantalla, una estrategia eficiente consiste en mantener un pool de nodos y añadir o quitar solo los estrictamente necesarios.

Este patrón evita trabajo repetido, reduce presión sobre el GC y hace que un `resize` continuo sea más estable que una reconstrucción completa en cada tick.

  • Precrea o reutiliza nodos si la estructura cambia mucho pero el tipo de elemento es siempre el mismo.
  • Usa `requestAnimationFrame` para reagrupar renders disparados por `resize`.
  • Actualiza estilos de layout en lote después de decidir cuántos nodos deben mostrarse.
JavaScript
28

DOM performance: evita reflows y trabajo innecesario

Aprende a reducir coste de renderizado agrupando cambios y minimizando lecturas/escrituras conflictivas del layout.

Código del tema: batch updates | DocumentFragment | requestAnimationFrame

📘 Teoría

Qué es el layout thrashing

Leer medidas y escribir estilos en cada iteración dispara coste.

1

Cuando consultas `offsetHeight/getBoundingClientRect` y justo después cambias estilos repetidamente, el navegador recalcula layout muchas veces.

2

Ese patrón degrada rendimiento sobre todo en listas largas o animaciones.

Patrón a evitar
for (const item of items) {
  const alto = item.offsetHeight; // lectura
  item.style.height = `${alto + 10}px`; // escritura
}

Batch updates: agrupar lecturas y escrituras

Primero mide, luego aplica cambios.

  • Evita `innerHTML +=` dentro de bucles.
  • Si creas muchos nodos, usa `DocumentFragment`.
  • Usa clases CSS en lote en lugar de estilos inline por nodo.
Patrón recomendado
const medidas = items.map((el) => el.offsetHeight);

items.forEach((el, i) => {
  el.style.height = `${medidas[i] + 10}px`;
});

Fragmentos y requestAnimationFrame

Dos herramientas simples para UIs más fluidas.

1

`DocumentFragment` permite montar estructura en memoria y hacer un solo append al DOM.

2

`requestAnimationFrame` coordina cambios visuales con el ciclo de pintado del navegador.

Insertar 100 items sin castigar el DOM
const frag = document.createDocumentFragment();

for (let i = 0; i < 100; i++) {
  const li = document.createElement('li');
  li.textContent = `Item ${i + 1}`;
  frag.appendChild(li);
}

lista.appendChild(frag);

Reutilizar nodos cuando cambia el layout

No siempre hace falta destruir y reconstruir toda la interfaz.

En interfaces que responden al tamaño de pantalla, una estrategia eficiente consiste en mantener un pool de nodos y añadir o quitar solo los estrictamente necesarios.

Este patrón evita trabajo repetido, reduce presión sobre el GC y hace que un `resize` continuo sea más estable que una reconstrucción completa en cada tick.

  • Precrea o reutiliza nodos si la estructura cambia mucho pero el tipo de elemento es siempre el mismo.
  • Usa `requestAnimationFrame` para reagrupar renders disparados por `resize`.
  • Actualiza estilos de layout en lote después de decidir cuántos nodos deben mostrarse.

🧪 Aprende probando

Ejemplo Ejemplo guiado: render masivo eficiente Genera lista grande con fragment para reducir repaints.
Ejemplo Demo interactiva: grid que reutiliza nodos al redimensionar Observa cómo una galería ajusta columnas y filas reutilizando celdas existentes y limitando el trabajo en cada `resize`.
Ejemplo Demo interactiva: layout exacto con requestAnimationFrame Explora un grid cerrado de 50 celdas que recalcula su reparto óptimo con `requestAnimationFrame` y una sola actualización coordinada por frame.

🏁 Retos

Reto Reto: evitar innerHTML incremental Sustituye un bucle con `innerHTML +=` por `map + join`.

🧰 Recursos

Test

Comprueba tus conocimientos con un test sobre JavaScript.

Test de JavaScript

¿Qué es esto?

Soy Cristian Eslava y a veces hago webs para procrastinar yo y vosotros 😉.

Esta la hice en febrero de 2026 para facilitar el aprendizaje de mis alumnxs. Aprender desarrollo web practicando. La idea es que crezca semanalmente con nuevos temas, tests y retos.

Inspirado en MDN, en W3Schools, en Codepen, en el crack de Manz y en mil sitios de documentación sobre desarrollo web. Quería aportar además de bloques teóricos con ejemplos, la gamificación de los retos y el sistema de test que ya tenía en culTest .

Si te gustó, si no te gustó, si quieres saludarme, o invitarme a 🍻 no dudes en escribirme en cristianeslava@gmail.com .