Evita los diseños grandes y complejos, y la paginación excesiva de diseños

El diseño es el aspecto a través del cual el navegador descifra la información geométrica de los elementos: su tamaño y ubicación en la página. Cada elemento posee información explícita o implícita sobre el tamaño, según la CSS que se usó, el contenido del elemento o un elemento principal. El proceso se denomina Diseño en Chrome.

El diseño es el aspecto a través del cual el navegador descifra la información geométrica de los elementos: su tamaño y ubicación en la página. Cada elemento posee información explícita o implícita sobre el tamaño, según la CSS que se usó, el contenido del elemento o un elemento principal. El proceso se denomina Diseño en Chrome (y navegadores derivados, como Edge) y Safari. En Firefox, se denomina Reprocesamiento, pero el proceso es el mismo.

Al igual que los cálculos de estilo, los problemas inmediatos del costo del diseño son los siguientes:

  1. La cantidad de elementos que requieren diseño, que es un subproducto del tamaño del DOM de la página.
  2. La complejidad de esos diseños.

Resumen

  • El diseño tiene un efecto directo en la latencia de interacción
  • El diseño suele abarcar todo el documento.
  • La cantidad de elementos del DOM afectará el rendimiento; por ello, debes evitar activar el diseño siempre que sea posible.
  • Evita los diseños sincrónicos forzados y la hiperpaginación de diseños; lee los valores de estilo y realiza cambios de estilo.

Efectos del diseño en la latencia de interacción

Cuando un usuario interactúa con la página, esas interacciones deben ser lo más rápidas posible. La cantidad de tiempo que tarda una interacción en completarse (que termina cuando el navegador presenta el siguiente fotograma para mostrar los resultados de la interacción) se conoce como latencia de interacción. Este es un aspecto del rendimiento de la página que la métrica Interacción a la siguiente pintura mide.

La cantidad de tiempo que tarda el navegador en presentar el siguiente fotograma en respuesta a una interacción del usuario se conoce como demora en la presentación de la interacción. El objetivo de una interacción es proporcionar información visual para indicarle al usuario que algo ocurrió, y las actualizaciones visuales pueden requerir cierta cantidad de trabajo de diseño para lograr ese objetivo.

Para mantener el INP de tu sitio web lo más bajo posible, es importante evitar el diseño siempre que sea posible. Si no es posible evitar el diseño por completo, es importante limitar ese trabajo de diseño para que el navegador pueda presentar el siguiente fotograma rápidamente.

Evita el diseño siempre que sea posible

Cuando cambias los estilos, el navegador verifica si alguno de los cambios requiere que se calcule el diseño y que se actualice el árbol de representación. Los cambios en las "propiedades geométricas", como el ancho, el alto, la opción izquierda o la parte superior, requieren diseño.

.box {
  width: 20px;
  height: 20px;
}

/**
  * Changing width and height
  * triggers layout.
  */

.box--expanded {
  width: 200px;
  height: 350px;
}

El diseño casi siempre se aplica a todo el documento. Si tienes muchos elementos, te tomará mucho tiempo descifrar las ubicaciones y las dimensiones de todos ellos.

Si no es posible evitar el diseño, la clave es volver a usar las Herramientas para desarrolladores de Chrome para ver cuánto tarda y determinar si el diseño es la causa del cuello de botella. Primero, abre Herramientas para desarrolladores, ve a la pestaña Cronograma, presiona Grabar e interactúa con tu sitio. Cuando dejes de grabar, verás un desglose del rendimiento de tu sitio:

Herramientas para desarrolladores que muestran un período prolongado en Layout.

Cuando profundizamos en el seguimiento del ejemplo anterior, vemos que se pasan más de 28 milisegundos dentro del diseño de cada fotograma, lo que, cuando tenemos 16 milisegundos para mostrar un fotograma en la pantalla en una animación, es demasiado alto. También podrás ver que Herramientas para desarrolladores te indicará el tamaño del árbol (1618 elementos en este caso) y la cantidad de nodos que necesitaban diseño (5 en este caso).

Ten en cuenta que el consejo general es evitar el diseño siempre que sea posible, aunque no siempre es posible evitarlo. En los casos en que no puedas evitar el diseño, debes saber que el costo del diseño tiene una relación con el tamaño del DOM. Aunque la relación entre los dos no tiene acoplamiento alto, los DOM de mayor tamaño suelen generar costos de diseño más altos.

Cómo evitar los diseños sincrónicos forzados

El envío de un marco a la pantalla se realiza en este orden:

Usar Flexbox como diseño

Primero se ejecuta JavaScript, luego los cálculos de estilo y luego el diseño. Sin embargo, es posible forzar a un navegador para que realice el diseño antes con JavaScript. Esto se denomina diseño sincrónico forzado.

Lo primero que se debe tener en cuenta es que, a medida que JavaScript se ejecuta, todos los valores de diseño anteriores del fotograma anterior ya se conocen y están disponibles para que los consultes. Si, por ejemplo, deseas escribir la altura de un elemento (lo llamaremos "cuadro") al comienzo del fotograma, puedes escribir un código como el siguiente:

// Schedule our function to run at the start of the frame:
requestAnimationFrame(logBoxHeight);

function logBoxHeight () {
  // Gets the height of the box in pixels and logs it out:
  console.log(box.offsetHeight);
}

Existen problemas si cambias los estilos del cuadro antes de solicitar su altura:

function logBoxHeight () {
  box.classList.add('super-big');

  // Gets the height of the box in pixels and logs it out:
  console.log(box.offsetHeight);
}

Ahora, para responder la pregunta de altura, el navegador primero debe aplicar el cambio de estilo (debido a que agregó la clase super-big) y, luego, ejecutar el diseño. Solo entonces podrá mostrar la altura correcta. Este es un trabajo innecesario y potencialmente costoso.

Por lo tanto, siempre debes agrupar las lecturas de estilo y realizarlas primero (cuando el navegador puede usar los valores de diseño del fotograma anterior) y, luego, realizar las escrituras necesarias:

Si se la hace correctamente, la función anterior debería verse de la siguiente manera:

function logBoxHeight () {
  // Gets the height of the box in pixels and logs it out:
  console.log(box.offsetHeight);

  box.classList.add('super-big');
}

En general, no deberías necesitar aplicar estilos y, luego, consultar valores; basta con usar los valores del último fotograma. Ejecutar los cálculos de estilo y el diseño de forma síncrona y antes de lo que quisiera el navegador implica posibles cuellos de botella, y no es algo que normalmente querrás hacer.

Cómo evitar la hiperpaginación de diseños

Hay una manera de empeorar los diseños sincrónicos forzados: hacer muchos de ellos en una sucesión rápida. Observa este código:

function resizeAllParagraphsToMatchBlockWidth () {
  // Puts the browser into a read-write-read-write cycle.
  for (let i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.width = `${box.offsetWidth}px`;
  }
}

Este código se repite indefinidamente en un grupo de párrafos y establece el ancho de cada párrafo para que coincida con el ancho de un elemento llamado "box". Parece inofensivo, pero el problema es que cada iteración del bucle lee un valor de estilo (box.offsetWidth) y, luego, lo usa inmediatamente para actualizar el ancho de un párrafo (paragraphs[i].style.width). En la siguiente iteración del bucle, el navegador debe tener en cuenta que los estilos cambiaron desde que se solicitó offsetWidth por última vez (en la iteración anterior), por lo que debe aplicar los cambios de estilo y ejecutar el diseño. Esto sucederá con cada iteración.

La solución para esta muestra es volver a leer y, luego, escribir los valores:

// Read.
const width = box.offsetWidth;

function resizeAllParagraphsToMatchBlockWidth () {
  for (let i = 0; i < paragraphs.length; i++) {
    // Now write.
    paragraphs[i].style.width = `${width}px`;
  }
}

Si deseas garantizar la seguridad, considera usar FastDOM, que agrupa automáticamente las lecturas y escrituras por ti y evita que actives diseños sincrónicos forzados o hiperpaginación de diseños de forma accidental.

Hero image de Unsplash, de Hal Gatewood.