¿Qué son los layout reflow y cómo prevenirlos?

Uno de los mayores problemas de performance web se produce por acción de un layout reflow. Aprende a identificarlos y solucionarlos y optimiza tu aplicación web con estos consejos.


Cuando solicitamos al navegador que nos muestre una URL, este tiene que realizar un renderizado para poder mostrarnos su aspecto visual. En este proceso que sigue el browser, una de las fases que se ve implicada es la del layout, en la cual me centraré en este post.

El layout hace referencia a la posición geométrica, forma y tamaño de los elementos que componen una página web (imágenes, bloques de texto, botones…). El navegador, una vez que ha construido el DOM y el CSSOM, y posteriormente el render tree o árbol de renderizado, tiene todos los datos que necesita para poder organizar los elementos en la página, es decir, realizar el proceso del layout.

Por ejemplo, si tenemos una imagen de 500x500px, el navegador, durante la etapa de layout, se ocupa de dejar reservado este espacio para ella, exactamente en las coordenadas que le corresponden, para cuando la imagen sea procesada durante la siguiente fase, que es la de painting o pintado.

Si en algún momento del ciclo de vida de la aplicación deseamos cambiar la posición o el tamaño de este elemento, se deberá producir un nuevo proceso de layout, donde el navegador volverá a repetir todos estos pasos para renderizar el elemento en el lugar que le corresponde. Esto se conoce como layout reflow o layout trashing, y el tiempo que pierde en volver a hacer este proceso se denomina layout cost o reflow cost.

El layout trashing supone una actualización de determinados elementos de la página web como el tamaño, el color, la forma o su localización, sobreescribiendo los estilos anteriores y los eventos del layout volviendo a recalcular el estilo y realizando un nuevo layout. Determinados triggers de CSS y animaciones pueden producir un layout reflow, así como determinados métodos de JavaScript para acceder al DOM y manipularlo.

¿Qué problemas supone para la performance de un sitio web un layout reflow?

Uno de los grandes problemas que implica el layout reflow es el impacto que este proceso tiene en la performance de un sitio web. Determinadas acciones ejecutan un nuevo proceso de renderizado que necesitan un tiempo para llevarse a cabo. Este tiempo impacta directamente en la velocidad de la carga de la página. Es por ello que debemos monitorizar exhaustivamente todos los reflows que se produzcan en nuestro sitio web, para reducir sus costes e intentar evitarlos si no son completamente necesarios.

Este coste que supone el layout reflow en el tiempo de carga de un sitio web, implica, como todos los eventos que afectan a la velocidad, un impacto negativo en la experiencia del usuario, y también un impacto negativo en el posicionamiento del sitio web en los motores de búsqueda.

crp-with-reflow.png

Ejemplo del Critical Render Path que ejecuta un navegador al solicitar una URL. Cuando se produce un layout reflow, los cálculos anteriores se invalidan y el proceso debe volver a ejecutarse de nuevo.

¿Qué variables influyen en el tiempo que tarda el navegador en realizar un layout reflow?

Cada técnica que desencadena un layout reflow tiene un coste diferente, es decir, que tarda un tiempo determinado para que se vuelva a producir la fase de layout. Además, este tiempo también viene dado por el uso de los diferentes motores de renderizado de los navegadores: Gecko para Firefox, Blink para Chrome, WebKit para Safari…

Por último, los otros dos elementos que influyen en el coste del layout reflow son la cantidad de elementos de los que se necesita volver a calcular sus estilos y pintar, y, en general, la complejidad del layout al completo.

¿Cómo puedo evitar un layout reflow en mi sitio web?

Como ya he dicho en los párrafos anteriores, determinadas propiedades de CSS modifican el tamaño y la posición de los elementos, y su uso tiene un coste concreto por cada una de ellas en el proceso del layout. Una vez que se han interpretado el DOM y el CSSOM, es importante que el navegador no vuelva a modificar el layout del sitio web para evitar performance bottlenecks (es decir, acciones que hagan que uno o varios elementos de un sitio produzcan un bloqueo de la performance ya que consumen todos los recursos de la CPU del navegador, producido por un layout reflow en este caso).

layout-thrashing-cheatsheet.jpg

Lista de propiedades CSS y métodos jQuery que pueden forzar un layout reflow. Fuente: devhints.io

Un ejemplo claro de este proceso: cuando se solicita al DOM la posición o el tamaño de un elemento, el resultado se puede tomar de los cálculos previos, si el navegador es consciente de que el DOM no ha sido manipulado, y toma el resultado del caché del layout. Esto se conoce como medición del DOM. Pero cuando queremos modificar o mutar el DOM, el navegador invalida los cálculos anteriores y vuelve a programar un nuevo recálculo. Si se realiza una medición del DOM durante este proceso, el navegador tiene que volver a recalcular el DOM al completo para poder ofrecer el resultado, ya que no existe caché del layout en este punto.

¿Y si necesito modificar alguno de los elementos de mi sitio web? ¿Es esto perjudicial para el tiempo de carga de mi web?

Es esencial evitar los reflows en la medida de lo posible, pero hay situaciones en las cuales necesitamos modificar de forma obligatoria los elementos de un sitio web.

El layout reflow puede producirse o bien de forma inesperada, o bien por acción del usuario al desencadenar un evento en la página, como un hover o un scroll. En este último caso, estas acciones no afectarían de forma negativa a la experiencia de usuario. En el caso de producirse reflows de forma inesperada, esto sí que supondría un impacto negativo en la experiencia del usuario, y también afectaría en la métrica del CLS (Cumulative Layout Shift), además de, obviamente, suponer un gran problema de performance web.

¿Cómo puedo monitorizar los layout reflows que se producen en mi sitio web y el coste que tienen?

Gracias a herramientas como Chrome Dev Tools, podemos auditar de forma rápida y fácil nuestra página web y detectar los layout reflows que se produzcan al desencadenar ciertos eventos en el layout, y también el coste que estos tienen en términos de performance.

Para abrir la herramienta solo tienes que pulsar F2 o Control + Shift + I en Windows, o Cmd + Opt + I en MAC. Ahí, seleccionamos la pestaña de “Performance” y pulsaremos en el botón de reload para recargar la página y comenzar a grabar. Interactuamos con nuestra página para medir los costes en la performance de cada acción y detenemos la grabación para obtener el informe de performance.

También podemos grabar y guardar varios informes para poder realizar cambios y experimentos sobre nuestra app y monitorizar las mejoras aplicadas y el impacto que han tenido sobre el tiempo de renderizado.

perf-dev-tools-1.gif

En el caso expuesto, el primer componente que aparece a la izquierda, al hacer hover el cuadrado se hace más grande gracias a la propiedad transform. En el de la derecha, al hacer hover se produce una variación de su ancho y alto, lo que desencadena un layout reflow, ya que el navegador tiene que invalidar los cálculos realizados anteriormente y volver a realizarlos, y de nuevo, ejecuta este proceso cuando el ratón se mueve fuera del elemento, provocando un segundo reflow.

En Dev Tools también podemos ver el coste que tiene esta acción:

perf-dev-tools-2.gif

Coste por emplear la propiedad de CSS transform para ampliar el elemento.

perf-dev-tools-3.gif

Coste por modificar el ancho y alto en CSS para ampliar el elemento.

En el primer caso, se tarda 4ms en el scripting, 3ms en el rendering y 1ms en el painting, mientras que en el segundo, el coste de ese layout reflow es de 22ms en el scripting, 10ms en el rendering y 2ms en el painting. La diferencia es clara, ¿verdad? Al hablar de milisegundos, tal vez el impacto en la experiencia de usuario no sea tan grande, pero en una aplicación web completa que encadene varios layout reflows, la suma de todos puede tener un gran impacto, provocando un layout trashing que debe ser monitorizado para poder implementar soluciones más eficaces.

¿Conocías la existencia de los layout trashing? Si todavía te ha quedado alguna duda sobre su monitorización, ¡no dudes en escribirme! :)

Y si quieres experimentar en tu navegador, puedes ver el ejemplo que he empleado para este post en este repositorio.