JavaScript suele ser el desencadenante de cambios visuales. Algunas veces, lo hace directamente mediante manipulaciones de estilo y, otras veces, mediante cálculos que generarán cambios visuales, como ordenar o buscar algunos datos. El JavaScript sincronizado incorrectamente o de larga ejecución puede ser una causa común de los problemas de rendimiento, y debes intentar minimizar su impacto siempre que sea posible.
Si se modifica el DOM, mediante la adición y eliminación de elementos, la modificación de atributos o clases, o la aplicación de animaciones, el navegador volverá a calcular los estilos de los elementos y, en muchos casos, diseñará (o reprocesará) la página o partes de ella. Este proceso se denomina cálculo de estilo computado.
La primera parte de los estilos de cómputos es crear un conjunto de selectores coincidentes, que es básicamente el navegador que averigua qué clases, seudoselectores y qué ID se aplican a un elemento determinado.
La segunda parte del proceso implica tomar todas las reglas de estilo de los selectores de coincidencias y descubrir qué estilos finales tiene el elemento.
Resumen
- Cómo reducir los costos de cálculo de estilo puede reducir la latencia de las interacciones
- Reduce la complejidad de tus selectores; usa una metodología centrada en la clase (por ejemplo, BEM).
- Reduce la cantidad de elementos en los que se deben realizar cálculos de estilo.
Establece el estilo del tiempo de recálculo y la latencia de interacción
La Interacción a la siguiente pintura (INP) es una métrica de rendimiento del entorno de ejecución centrada en el usuario que evalúa la capacidad de respuesta general de una página ante las entradas del usuario. Cuando esta métrica evalúa la latencia de interacción, mide el tiempo que transcurre desde que el usuario interactúa con la página hasta que el navegador pinta el siguiente fotograma que muestra las actualizaciones visuales correspondientes que se realizaron en la interfaz de usuario.
Un componente significativo de una interacción es el tiempo que lleva pintar el siguiente fotograma. El trabajo de renderización que se realiza para presentar el siguiente fotograma se compone de muchas partes, incluido el cálculo de los estilos de página que ocurren justo antes del trabajo de diseño, pintura y composición. Si bien este artículo se centra únicamente en los costos de cálculo de estilo, es importante destacar que la reducción de cualquier parte de la fase de renderización inherente a la interacción reducirá su latencia total, incluido el cálculo de estilo.
Reduce la complejidad de tus selectores
En el caso más simple, puedes hacer referencia a un elemento de tu CSS con una sola clase:
.title {
/* styles */
}
Sin embargo, a medida que un proyecto se expande, es probable que resulte en CSS más complejas, de manera que podrías terminar con selectores como los siguientes:
.box:nth-last-child(-n+1) .title {
/* styles */
}
Para saber cómo se aplican estos estilos a la página, el navegador debe preguntarse de manera efectiva si este es un elemento con una clase de title
que tiene un elemento superior que resulta ser el menos enésimo elemento secundario más 1 elemento con una clase de box
. Determinar esto puede llevar mucho tiempo, según el selector que se utilice y el navegador en cuestión. El comportamiento previsto del selector podría cambiarse, en cambio, a una clase:
.final-box-title {
/* styles */
}
Es posible que no estés de acuerdo con el nombre de la clase, pero el trabajo ahora es mucho más simple para el navegador. En la versión anterior, para saber, por ejemplo, que el elemento es el último de su tipo, el navegador primero debe saber todo sobre todos los demás elementos y si hay algún elemento posterior que podría ser nth-last-child
, lo que podría ser más costoso que simplemente hacer coincidir el selector con el elemento porque su clase coincide.
Reduce la cantidad de elementos a los que se les aplica diseño
Otra consideración sobre el rendimiento, que suele ser el factor más importante para muchas actualizaciones de estilo, es el gran volumen de trabajo que debe realizarse cuando cambia un elemento.
En términos generales, el peor de los costos de calcular el estilo calculado de los elementos es la cantidad de elementos multiplicados por el recuento del selector, ya que se debe verificar cada elemento al menos una vez con cada estilo para ver si coincide.
A menudo, los cálculos de estilo se pueden orientar directamente a unos pocos elementos en lugar de invalidar la página en su totalidad. En los navegadores actualizados, esto suele ser un problema menor, ya que no es necesario que verifiquen todos los elementos potencialmente afectados por un cambio. Por otro lado, los navegadores más antiguos no siempre están tan optimizados para estas tareas. Siempre que puedas, debes reducir la cantidad de elementos invalidados.
Mide el costo de recalcular el estilo
Una forma de medir el costo de recalcular el estilo es usar el panel de rendimiento de Herramientas para desarrolladores de Chrome. Para comenzar, abre Herramientas para desarrolladores, ve a la pestaña Rendimiento, presiona Grabar e interactúa con la página. Cuando detengas la grabación, verás una imagen similar a la que se muestra a continuación:
La franja de la parte superior es un gráfico tipo llama en miniatura que también traza fotogramas por segundo. Cuanto más cerca esté la actividad de la parte inferior de la franja, más rápido será el navegador pintando los fotogramas. Si ves que el gráfico tipo llama se nivela en la parte superior con franjas rojas sobre él, significa que hay trabajo que está causando los fotogramas de larga duración.
Si tienes un fotograma de larga duración durante una interacción, como el desplazamiento, será necesario realizar un escrutinio más. Si tienes un bloque púrpura grande, acerca la actividad y selecciona cualquier trabajo con la etiqueta Recalculate Style para obtener más información sobre trabajos de recálculo de estilo potencialmente costosos.
En esta captura, hay un trabajo de recalcular de estilo de larga duración que tarda un poco más de 25 ms.
Si haces clic en el evento, recibirás una pila de llamadas. Si el trabajo de renderización se debió a una interacción del usuario, se llamará al lugar de tu JavaScript responsable de activar el cambio de diseño. Además de eso, también obtienes la cantidad de elementos afectados por el cambio (un poco más de 900 en este caso) y el tiempo que tardó en hacer el trabajo de cálculo del estilo. Puedes usar esta información para intentar encontrar una solución en tu código.
Usa Bloquear, Elemento y Modificador
Los enfoques de programación, como BEM (Bloque, elemento, modificador), en realidad se integran en los beneficios de rendimiento de coincidencia del selector que se mencionaron anteriormente, ya que recomiendan que todo tenga una sola clase y, cuando se necesita jerarquía, esta también se integra en el nombre de la clase:
.list {
/* Styles */
}
.list__list-item {
/* Styles */
}
Si necesitas algún modificador, como en el ejemplo anterior (en el que queremos hacer algo especial para el último elemento secundario), puedes agregarlo de la siguiente manera:
.list__list-item--last-child {
/* Styles */
}
Si estás buscando una buena manera de organizar tu CSS, BEM es un buen punto de partida, tanto desde el punto de vista de la estructura, como debido a las simplificaciones de búsqueda de estilo que promueve la metodología.
Si no te gusta BEM, hay otras formas de abordar tu CSS, pero las consideraciones de rendimiento deben evaluarse junto con la ergonomía del enfoque.
Recursos
Hero image de Unsplash, de Markus Spiske.