Cumulative Layout Shift (CLS)

Navegadores compatibles

  • 77
  • 79
  • x
  • x

Origen

Los cambios de diseño inesperados pueden interrumpir la experiencia del usuario de muchas maneras, desde hacer que pierdan su lugar mientras leen si el texto se mueve repentinamente, hasta hacer que hagan clic en el vínculo o botón incorrecto. En algunos casos, esto puede causar daños graves.

Un cambio repentino en el diseño hace que el usuario confirme un pedido grande que pretendía cancelar.

Por lo general, el movimiento inesperado del contenido de la página ocurre cuando los recursos se cargan de forma asíncrona o cuando los elementos del DOM se agregan de forma dinámica a la página antes que el contenido existente. Los cambios de diseño pueden deberse a imágenes o videos con dimensiones desconocidas, fuentes que se renderizan más grandes o más pequeñas que su resguardo inicial, o anuncios o widgets de terceros que cambian de tamaño de forma dinámica.

Las diferencias entre el funcionamiento de un sitio en desarrollo y la manera en que los usuarios lo experimentan empeoran este problema. Por ejemplo:

  • El contenido personalizado o de terceros suele comportarse de forma diferente en el desarrollo y en la producción.
  • A menudo, las imágenes de prueba ya se encuentran en la caché del navegador del desarrollador, pero tardan más en cargarse para el usuario final.
  • Las llamadas a la API que se ejecutan localmente suelen ser tan rápidas que los retrasos imperceptibles en el desarrollo pueden volverse sustanciales en la producción.

La métrica Cambio de diseño acumulado (CLS) te ayuda a abordar este problema midiendo la frecuencia con la que ocurre para los usuarios reales.

¿Qué es CLS?

CLS es una medida del aumento de actividad más grande de las puntuaciones de cambio de diseño por cada cambio de diseño inesperado que ocurre durante todo el ciclo de vida de una página.

Un cambio de diseño ocurre cada vez que un elemento visible cambia su posición de un marco renderizado al siguiente. (Más adelante en esta guía, encontrarás detalles sobre cómo se calculan las puntuaciones individuales de cambio de diseño).

Un aumento de actividad de cambios de diseño, conocido como ventana de sesión, ocurre cuando se producen uno o más cambios de diseño individuales en una sucesión rápida, con menos de 1 segundo entre cada cambio y un máximo de 5 segundos para la duración total de la ventana.

El aumento de actividad más grande es la ventana de sesión con la puntuación acumulada máxima de todos los cambios de diseño dentro de esa ventana.

Ejemplo de ventanas de sesión. Las barras azules representan las puntuaciones de cada cambio de diseño individual.

¿Qué es una buena puntuación de CLS?

Para proporcionar una buena experiencia del usuario, los sitios deben esforzarse por tener una puntuación de CLS de 0.1 o menos. Para asegurarte de alcanzar este objetivo para la mayoría de los usuarios, un buen umbral para medir es el percentil 75 de las cargas de páginas, segmentadas entre dispositivos móviles y computadoras de escritorio.

Los valores de CLS buenos son 0.1 o menos, los valores malos son mayores que 0.25 y cualquier valor intermedio debe mejorarse
Los valores de CLS correctos son 0.1 o menos. Los valores pobres son mayores que 0.25.

Para obtener más información sobre la investigación y la metodología detrás de esta recomendación, consulta Define los umbrales de las métricas web esenciales.

El diseño cambia en detalle

Los cambios de diseño se definen a través de la API de inestabilidad de diseño, que informa entradas layout-shift cada vez que un elemento visible dentro del viewport cambia su posición inicial (por ejemplo, su posición superior e izquierda en el modo de escritura predeterminado) entre dos fotogramas. Esos elementos se consideran inestables.

Ten en cuenta que los cambios de diseño solo ocurren cuando los elementos existentes cambian su posición inicial. Si se agrega un elemento nuevo al DOM o si se modifica el tamaño de un elemento existente, no se considerará un cambio de diseño, siempre y cuando el cambio no provoque que otros elementos visibles cambien su posición inicial.

Puntuación de cambio de diseño

Para calcular la puntuación de cambio de diseño, el navegador observa el tamaño del viewport y el movimiento de los elementos inestables en el viewport entre dos marcos renderizados. La puntuación del cambio de diseño es el producto de dos medidas de ese movimiento: la fracción de impacto y la fracción de distancia (ambas se definen a continuación).

layout shift score = impact fraction * distance fraction

Fracción de impacto

La fracción de impacto mide cómo los elementos inestables afectan el área del viewport entre dos fotogramas.

La fracción de impacto para un marco determinado es una combinación de las áreas visibles de todos los elementos inestables de ese marco y el marco anterior, como una fracción del área total del viewport.

Ejemplo de la fracción de impacto con un elemento inestable
Si un elemento cambia de posición, su posición anterior y actual contribuyen a su fracción de impacto.

En la imagen anterior, hay un elemento que ocupa la mitad del viewport en un fotograma. Luego, en el siguiente fotograma, el elemento se desplaza hacia abajo un 25% de la altura de la viewport. El rectángulo rojo y punteado indica la unión del área visible del elemento en ambos marcos, que, en este caso, es el 75% del total del viewport, por lo que su fracción de impacto es 0.75.

Fracción de distancia

La otra parte de la ecuación de puntuación de cambio de diseño mide la distancia que se mueven los elementos inestables en relación con el viewport. La fracción de distancia es la mayor distancia horizontal o vertical que se movió un elemento inestable en el marco dividida por la dimensión más grande del viewport (ancho o altura, lo que sea mayor).

Ejemplo de fracción de distancia con un elemento inestable
La fracción de distancia mide qué tan lejos se movió un elemento en el viewport.

En el ejemplo anterior, la dimensión más grande del viewport es la altura, y el elemento inestable se movió un 25% de la altura del viewport, lo que hace que la fracción de distancia sea 0.25.

Por lo tanto, en este ejemplo, la fracción de impacto es 0.75 y la fracción de distancia es 0.25, por lo que la puntuación de cambio de diseño es 0.75 * 0.25 = 0.1875.

Ejemplos

En el siguiente ejemplo, se muestra cómo agregar contenido a un elemento existente afecta la puntuación del cambio de diseño:

Ejemplo de cambio de diseño con varios _elementos inestables y estables_
Si agregas un botón en la parte inferior del cuadro gris, el cuadro verde se empuja hacia abajo y parcialmente fuera del viewport.

En este ejemplo, el cuadro gris cambia de tamaño, pero su posición inicial no cambia, por lo que no es un elemento inestable.

El botón "¡Haz clic!" no estaba en el DOM anteriormente, por lo que su posición de inicio tampoco cambia.

Sin embargo, la posición inicial del cuadro verde cambia, pero como se movió parcialmente fuera del viewport, no se considera el área invisible al calcular la fracción de impacto. La unión de las áreas visibles para el cuadro verde en ambos marcos (ilustrados por el rectángulo rojo de puntos) es la misma que el área del cuadro verde en el primer marco, el 50% de la ventana de visualización. La fracción de impacto es 0.5.

La fracción de distancia se ilustra con la flecha púrpura. El cuadro verde se desplazó hacia abajo aproximadamente un 14% del viewport, por lo que la fracción de distancia es 0.14.

La puntuación del cambio de diseño es 0.5 x 0.14 = 0.07.

En el siguiente ejemplo, se muestra cómo varios elementos inestables afectan la puntuación del cambio de diseño de una página:

Ejemplo de cambio de diseño con _elementos inestables_ y estables_ y recorte de viewport
A medida que aparecen más nombres en la lista, los existentes se mueven para conservar el orden alfabético.

En el primer marco de la imagen anterior, hay cuatro resultados de una solicitud de API para animales, ordenados alfabéticamente. En el segundo marco, se agregan más resultados a la lista ordenada.

El primer elemento de la lista (“Cat”) no cambia su posición inicial entre marcos, por lo que es estable. Asimismo, los nuevos elementos agregados a la lista no estaban antes en el DOM, por lo que sus posiciones de inicio tampoco cambian. Sin embargo, los elementos etiquetados como "Perro", "Caballo" y "Zebra" cambian sus posiciones iniciales, lo que los convierte en elementos inestables.

Una vez más, los rectángulos rojos y punteados representan la unión de estos tres elementos inestables antes y después de las áreas, que en este caso corresponde aproximadamente al 60% del área del viewport (fracción de impacto de 0.60).

Las flechas representan las distancias que los elementos inestables se desplazan desde sus posiciones iniciales. El elemento "Zebra", representado por la flecha azul, se movió más, aproximadamente en un 30% de la altura de la viewport. Eso hace que la fracción de distancia de este ejemplo sea 0.3.

La puntuación del cambio de diseño es 0.60 x 0.3 = 0.18.

Comparación entre los cambios de diseño esperados y los inesperados

No todos los cambios de diseño son malos. De hecho, muchas aplicaciones web dinámicas cambian con frecuencia la posición de inicio de los elementos en la página. Un cambio de diseño solo es malo si el usuario no lo espera.

Cambios de diseño iniciados por el usuario

Los cambios de diseño que ocurren en respuesta a las interacciones del usuario (como hacer clic o presionar un vínculo, presionar un botón o escribir en un cuadro de búsqueda) son correctos, siempre y cuando el cambio se produzca lo suficientemente cerca de la interacción como para que el usuario pueda tener una relación clara.

Por ejemplo, si una interacción del usuario activa una solicitud de red que puede tardar un poco en completarse, es mejor crear un espacio de inmediato y mostrar un indicador de carga para evitar un cambio de diseño desagradable cuando se completa la solicitud. Si el usuario no se da cuenta de que algo se está cargando o no tiene una idea de cuándo el recurso estará listo, es posible que intente hacer clic en otro elemento mientras espera, algo que podría salirse de debajo.

Los cambios de diseño que se produzcan en un plazo de 500 milisegundos desde la entrada del usuario tendrán establecida la marca hadRecentInput para que se puedan excluir de los cálculos.

Animaciones y transiciones

Cuando se usan bien, las animaciones y transiciones son una excelente manera de actualizar el contenido de la página sin sorprender al usuario. El contenido que cambia de forma abrupta e inesperada en la página casi siempre crea una mala experiencia del usuario. Sin embargo, el contenido que se mueve de forma gradual y natural de una posición a la siguiente suele ayudar al usuario a comprender mejor lo que sucede y guiarlo entre cambios de estado.

Asegúrate de respetar la configuración del navegador prefers-reduced-motion, ya que algunos visitantes del sitio pueden experimentar efectos negativos o problemas de atención a causa de la animación.

La propiedad transform de CSS te permite animar elementos sin activar cambios de diseño:

  • En lugar de cambiar las propiedades height y width, usa transform: scale().
  • Para mover los elementos, evita cambiar las propiedades top, right, bottom o left, y usa transform: translate() en su lugar.

Cómo medir la métrica CLS

CLS se puede medir en el lab o en el campo, y está disponible en las siguientes herramientas:

Herramientas de campo

Herramientas del lab

Cómo medir los cambios de diseño en JavaScript

Para medir los cambios de diseño en JavaScript, usa la API de inestabilidad de diseño.

En el siguiente ejemplo, se muestra cómo crear un PerformanceObserver para registrar entradas de layout-shift en la consola:

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('Layout shift:', entry);
  }
}).observe({type: 'layout-shift', buffered: true});

Mide la CLS en JavaScript

Para medir el CLS en JavaScript, debes agrupar estas entradas de layout-shift inesperadas en sesiones y calcular el valor máximo de la sesión. Puedes consultar el código fuente de la biblioteca de JavaScript web vitals, que contiene una implementación de referencia sobre cómo se calcula la CLS.

En la mayoría de los casos, el valor CLS actual en el momento en que se descarga la página es el valor CLS final para esa página, pero hay algunas excepciones importantes, como se indica en la siguiente sección. La biblioteca de JavaScript web vitals los tiene en cuenta tanto como sea posible, dentro de las limitaciones de las APIs web.

Diferencias entre la métrica y la API

  • Si una página se carga en segundo plano, o si lo hace antes de que el navegador pinte algún contenido, no se debería informar ningún valor de CLS.
  • Si se restablece una página desde la memoria caché atrás/adelante, su valor de CLS debería restablecerse a cero, ya que los usuarios experimentan esta visita como una visita de página distinta.
  • La API no informa entradas layout-shift para los cambios que ocurren dentro de iframes, pero la métrica lo hace porque forman parte de la experiencia del usuario de la página. Esto puede mostrarse como una diferencia entre CrUX y RUM. Para medir adecuadamente la CLS, debes considerarlos. Los submarcos pueden usar la API para informar sus entradas layout-shift al marco superior para la agregación.

Además de estas excepciones, CLS tiene algo de complejidad adicional debido a que mide toda la vida útil de una página:

  • Los usuarios pueden mantener una pestaña abierta durante un mucho tiempo: días, semanas o meses. De hecho, es posible que un usuario nunca cierre una pestaña.
  • En los sistemas operativos de dispositivos móviles, los navegadores no suelen ejecutar devoluciones de llamada de descarga de páginas para las pestañas en segundo plano, lo que dificulta informar el valor "final".

Para manejar estos casos, se debe informar CLS cada vez que una página se encuentra en segundo plano, además de cada vez que está descargada (el evento visibilitychange abarca ambas situaciones). Los sistemas analíticos que reciben estos datos deberán calcular el valor CLS final en el backend.

En lugar de memorizar y analizar todos estos casos por tu cuenta, los desarrolladores pueden usar la biblioteca de JavaScript web-vitals para medir el CLS, que tiene en cuenta todo lo mencionado anteriormente, excepto el caso de iframe:

import {onCLS} from 'web-vitals';

// Measure and log CLS in all situations
// where it needs to be reported.
onCLS(console.log);

Cómo mejorar CLS

Si necesitas más orientación para identificar cambios de diseño en el campo y usar datos de lab para optimizarlos, consulta nuestra guía sobre optimización de CLS.

Recursos adicionales

Registro de cambios

Ocasionalmente, se descubren errores en las APIs que se usan para medir métricas y, a veces, en las definiciones de las métricas en sí. Como resultado, a veces es necesario realizar cambios, que pueden aparecer como mejoras o regresiones en tus informes y paneles internos.

Para ayudarte a administrar esto, todos los cambios en la implementación o definición de estas métricas aparecerán en este Registro de cambios.

Si tienes comentarios sobre estas métricas, puedes enviarlos en el grupo de Google web-vitals-feedback.