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, como 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 empleada, el contenido del elemento o un elemento principal. El proceso se llama 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 empleada, el contenido del elemento o un elemento principal. El proceso se llama 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 con los cálculos de estilo, las preocupaciones inmediatas por el costo del diseño son las 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 normalmente se aplica a todo el documento.
  • La cantidad de elementos del DOM afectará el rendimiento; por eso, debes evitar la activación del diseño siempre que sea posible.
  • Evita los diseños sincrónicos forzados y la paginación excesiva 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 mide la métrica Interaction to Next Paint.

La cantidad de tiempo que tarda el navegador en presentar el siguiente fotograma en respuesta a una interacción del usuario se conoce como el retraso en la presentación de la interacción. El objetivo de una interacción es proporcionar comentarios visuales para indicar al usuario que algo ha ocurrido, y las actualizaciones visuales pueden implicar 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 diseños, el navegador verifica si alguno de los cambios requiere que se calcule el diseño y que se actualice el árbol de renderización. Los cambios en las “propiedades geométricas”, como el ancho, la altura, la 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 llevará mucho tiempo averiguar 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 tiempo tarda y determinar si el diseño es la causa del cuello de botella. Primero, abre Herramientas para desarrolladores, ve a la pestaña Línea de tiempo, 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 mucho tiempo en Layout.

Al profundizar en el seguimiento del ejemplo anterior, vemos que se pasan más de 28 milisegundos dentro del diseño de cada fotograma, que, cuando tenemos 16 milisegundos para obtener un fotograma en pantalla en una animación, es demasiado alto. También puedes ver que Herramientas para desarrolladores te indicará el tamaño del árbol (1618 elementos en este caso) y cuántos nodos 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 evitar el diseño. En los casos en los que no puedas evitar el diseño, ten en cuenta que su costo está relacionado con el tamaño del DOM. Aunque la relación entre los dos no es de acoplamiento alto, los DOM más grandes generalmente generarán costos de diseño más altos.

Evita los diseños sincrónicos forzados

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

Uso de Flexbox para el diseño.

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

Lo primero que debes tener en cuenta es que, a medida que JavaScript se ejecuta, todos los valores de diseño anteriores del fotograma anterior son conocidos y están disponibles para que los consultes. Por lo tanto, si, por ejemplo, deseas escribir la altura de un elemento (lo llamaremos "cuadro") al comienzo del marco, 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);
}

Se puede producir un problema si cambiaste los estilos del cuadro antes de averiguar 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 a la pregunta de altura, el navegador primero debe aplicar el cambio de estilo (debido a que se agregó la clase super-big) y, luego, ejecutar el diseño. Solo entonces podrá devolver la altura correcta. Este es un trabajo innecesario y potencialmente costoso.

Por este motivo, siempre debes agrupar las lecturas de estilo y hacerlas primero (donde el navegador puede usar los valores de diseño del fotograma anterior) y, luego, realizar las escrituras:

Si lo haces correctamente, la función anterior debería ser la siguiente:

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ía ser necesario aplicar estilos y, luego, consultar valores; bastará con usar los valores del último fotograma. La ejecución de los cálculos de estilo y el diseño de forma síncrona y antes de lo que el navegador quisiera podría generar cuellos de botella potenciales, y no es algo que normalmente querrás hacer.

Evita la hiperpaginación de diseños

Hay una forma de empeorar aún más los diseños sincrónicos forzados: crear muchos diseños 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 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 bastante inofensivo, pero el problema es que cada iteración del bucle lee un valor de estilo (box.offsetWidth) y, luego, lo usa de inmediato para actualizar el ancho de un párrafo (paragraphs[i].style.width). En la próxima iteración del bucle, el navegador debe tener en cuenta el hecho de 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á en 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 quieres garantizar la seguridad, considera usar FastDOM, que agrupa automáticamente las lecturas y escrituras por ti, y debería evitar que actives diseños sincrónicos forzados o una hiperpaginación de diseños de forma accidental.

Hero image de Unsplash, de Hal Gatewood.