Cómo solucionar problemas de cambio de diseño acumulativo (CLS)

Publicado: 2022-03-10
Resumen rápido ↬ La iniciativa Core Web Vitals de Google ha tomado por asalto los mundos de SEO y rendimiento web y muchos sitios están ocupados optimizando su experiencia de página para maximizar el factor de clasificación. La métrica de cambio de diseño acumulativo está causando problemas a muchos sitios, así que echemos un vistazo a las formas de abordar cualquier problema para esa métrica.

El cambio de diseño acumulativo (CLS) intenta medir esos movimientos discordantes de la página a medida que el contenido nuevo, ya sean imágenes, anuncios o lo que sea, entra en juego más tarde que el resto de la página. Calcula una puntuación basada en la cantidad de la página que se mueve inesperadamente y con qué frecuencia. Estos cambios de contenido son muy molestos, lo que hace que pierda su lugar en un artículo que ha comenzado a leer o, peor aún, que haga clic en el botón equivocado.

En este artículo, voy a discutir algunos patrones front-end para reducir CLS . No voy a hablar demasiado sobre la medición de CLS, ya que ya lo cubrí en un artículo anterior. Tampoco hablaré demasiado sobre la mecánica de cómo se calcula CLS: Google tiene buena documentación sobre eso, y The Almost-Complete Guide to Cumulative Layout Shift de Jess Peck también es una inmersión profunda increíble en eso. Sin embargo, daré un poco de información necesaria para comprender algunas de las técnicas.

Por qué CLS es diferente

CLS es, en mi opinión, el más interesante de Core Web Vitals, en parte porque es algo que nunca antes habíamos medido ni optimizado. Por lo tanto, a menudo requiere nuevas técnicas y formas de pensar para intentar optimizarlo. Es una bestia muy diferente a los otros dos Core Web Vitals.

Mirando brevemente los otros dos Core Web Vitals, Largest Contentful Paint (LCP) hace exactamente lo que sugiere su nombre y es más un giro en las métricas de carga anteriores que miden qué tan rápido se carga la página. Sí, hemos cambiado la forma en que definimos la experiencia del usuario de la carga de la página para observar la velocidad de carga del contenido más relevante , pero básicamente reutiliza las técnicas antiguas para garantizar que el contenido se cargue lo más rápido posible. Cómo optimizar su LCP debería ser un problema relativamente bien entendido para la mayoría de las páginas web.

First Input Delay (FID) mide cualquier retraso en las interacciones y parece no ser un problema para la mayoría de los sitios. Optimizar eso generalmente es una cuestión de limpiar (¡o reducir!) su JavaScript y generalmente es específico del sitio. Eso no quiere decir que resolver problemas con estas dos métricas sea fácil, pero son problemas razonablemente bien entendidos.

Una de las razones por las que CLS es diferente es que se mide a lo largo de la vida útil de la página : ¡esa es la parte "acumulativa" del nombre! Los otros dos Core Web Vitals se detienen después de que el componente principal se encuentra en la página después de la carga (para LCP) o para la primera interacción (para FID). Esto significa que nuestras herramientas tradicionales basadas en laboratorio, como Lighthouse, a menudo no reflejan completamente el CLS, ya que solo calculan el CLS de carga inicial. En la vida real, un usuario se desplazará hacia abajo en la página y puede obtener más contenido que provoque más turnos.

CLS también es un número un poco artificial que se calcula en función de la cantidad de página que se mueve y con qué frecuencia. Mientras que LCP y FID se miden en milisegundos, CLS es un número sin unidades generado por un cálculo complejo. Queremos que la página sea 0.1 o inferior para pasar este Core Web Vital. Cualquier valor por encima de 0,25 se considera "pobre".

Los turnos causados ​​por la interacción del usuario no se cuentan . Esto se define como dentro de los 500 ms de un conjunto específico de interacciones del usuario, aunque se excluyen los eventos de puntero y el desplazamiento. Se supone que un usuario que hace clic en un botón puede esperar que aparezca contenido, por ejemplo, al expandir una sección colapsada.

CLS se trata de medir cambios inesperados . El desplazamiento no debería hacer que el contenido se mueva si una página está construida de manera óptima, y ​​de manera similar, pasar el cursor sobre la imagen de un producto para obtener una versión ampliada, por ejemplo, tampoco debería hacer que el otro contenido salte. Pero, por supuesto, hay excepciones y esos sitios deben considerar cómo reaccionar ante esto.

CLS también evoluciona continuamente con ajustes y correcciones de errores. Se acaba de anunciar un cambio mayor que debería dar un respiro a las páginas de larga duración, como las aplicaciones de una sola página (SPA) y las páginas de desplazamiento infinito, que muchos sintieron que fueron penalizadas injustamente en CLS. En lugar de acumular turnos durante todo el tiempo de la página para calcular la puntuación de CLS como se ha hecho hasta ahora, la puntuación se calculará en función del mayor conjunto de turnos dentro de una ventana de tiempo específica.

Esto significa que si tiene tres fragmentos de CLS de 0,05, 0,06 y 0,04, anteriormente esto se habría registrado como 0,15 (es decir, por encima del límite "bueno" de 0,1), mientras que ahora se calificará como 0,06. Todavía es acumulativo en el sentido de que la puntuación puede estar formada por turnos separados dentro de ese período de tiempo (es decir, si esa puntuación CLS de 0,06 fue causada por tres turnos separados de 0,02), pero ya no es acumulativa durante la vida útil total de la página. .

Dicho esto, si resuelve las causas de ese cambio de 0,06, entonces su CLS se informará como el siguiente más grande (0,05), por lo que todavía está analizando todos los cambios durante la vida útil de la página; solo elige informar solo el más grande como la puntuación CLS.

Con esa breve introducción a parte de la metodología sobre CLS, ¡pasemos a algunas de las soluciones ! Básicamente, todas estas técnicas implican reservar la cantidad correcta de espacio antes de que se cargue el contenido adicional, ya sea contenido multimedia o con inyección de JavaScript, pero hay algunas opciones diferentes disponibles para que los desarrolladores web hagan esto.

¡Más después del salto! Continúe leyendo a continuación ↓

Establecer ancho y alto en imágenes e iFrames

He escrito sobre esto antes, pero una de las cosas más fáciles que puede hacer para reducir CLS es asegurarse de tener los atributos de width y height establecidos en sus imágenes . Sin ellos, una imagen hará que el contenido subsiguiente se desplace para darle paso después de que se descargue:

Un diseño de ejemplo con un título y dos párrafos, donde el segundo párrafo tiene que desplazarse hacia abajo para hacer espacio para una imagen.
Cambio de diseño después de cargar la imagen. (Vista previa grande)

Esto es simplemente una cuestión de cambiar el marcado de su imagen de:

 <img src="hero_image.jpg" alt="...">

Para:

 <img src="hero_image.jpg" alt="..." width="400" height="400">

Puede encontrar las dimensiones de la imagen abriendo DevTools y pasando el cursor sobre (o tocando) el elemento.

Captura de pantalla de Chrome Dev Tools que muestra la imagen, el tamaño renderizado, la relación de aspecto renderizada, el tamaño intrínseco, la relación de aspecto intrínseca, el tamaño del archivo y la fuente actual.
Chrome DevTools muestra las dimensiones de la imagen y las relaciones de aspecto al pasar el cursor sobre un elemento. (Vista previa grande)

Aconsejo usar el Tamaño intrínseco (que es el tamaño real de la fuente de la imagen) y el navegador los reducirá al tamaño representado cuando use CSS para cambiarlos.

Sugerencia rápida : si, como yo, no puede recordar si es ancho y alto o alto y ancho, piense en ello como coordenadas X e Y, por lo que, como X, el ancho siempre se da primero.

Si tiene imágenes receptivas y usa CSS para cambiar las dimensiones de la imagen (por ejemplo, para restringirla a un max-width del 100% del tamaño de la pantalla), estos atributos se pueden usar para calcular la height , siempre que recuerde anular esto para auto en tu CSS:

 img { max-width: 100%; height: auto; }

Todos los navegadores modernos admiten esto ahora, aunque no lo hicieron hasta hace poco, como se explica en mi artículo. Esto también funciona para elementos <picture> e imágenes srcset (establezca el width y la height en el elemento img alternativo), aunque todavía no para imágenes de diferentes relaciones de aspecto: se está trabajando en ello y, hasta entonces, aún debe establecer el width y la height ¡ya que cualquier valor será mejor que los valores predeterminados de 0 por 0 !

Esto también funciona en imágenes nativas con carga diferida (aunque Safari todavía no admite la carga diferida nativa de forma predeterminada).

La nueva propiedad CSS aspect-ratio

La técnica de width y height anterior, para calcular el alto de las imágenes receptivas, se puede generalizar a otros elementos utilizando la nueva propiedad aspect-ratio CSS, que ahora es compatible con los navegadores basados ​​en Chromium y Firefox, pero también está en Safari Technology Preview para que con suerte, eso significa que pronto llegará a la versión estable.

Por lo tanto, podría usarlo en un video incrustado, por ejemplo, en una proporción de 16: 9:

 video { max-width: 100%; height: auto; aspect-ratio: 16 / 9; }
 <video controls width="1600" height="900" poster="..."> <source src="/media/video.webm" type="video/webm"> <source src="/media/video.mp4" type="video/mp4"> Sorry, your browser doesn't support embedded videos. </video>

Curiosamente, sin definir la propiedad aspect-ratio , los navegadores ignorarán la altura de los elementos de video receptivos y usarán una relación de aspecto predeterminada de 2:1, por lo que se necesita lo anterior para evitar un cambio de diseño aquí.

En el futuro, incluso debería ser posible establecer la aspect-ratio dinámicamente en función de los atributos del elemento utilizando aspect-ratio: attr(width) / attr(height); pero lamentablemente esto no es compatible todavía.

O incluso puede usar aspect-ratio en un elemento <div> para algún tipo de control personalizado que está creando para que responda:

 #my-square-custom-control { max-width: 100%; height: auto; width: 500px; aspect-ratio: 1; }
 <div></div>

Para aquellos navegadores que no son compatibles aspect-ratio puede usar el antiguo truco de la parte inferior del relleno pero, con la simplicidad de la aspect-ratio más nueva y el amplio soporte (especialmente una vez que se pasa de Safari Technical Preview a Safari normal), es Es difícil justificar ese método más antiguo.

Chrome es el único navegador que retroalimenta CLS a Google y es compatible con el significado aspect-ratio que resolverá sus problemas de CLS en términos de Core Web Vitals. No me gusta priorizar las métricas sobre los usuarios, pero el hecho de que los otros navegadores Chromium y Firefox tengan esto y que Safari lo tenga pronto, y que esta sea una mejora progresiva significa que yo diría que estamos en el punto donde puede dejar atrás el truco del relleno inferior y escribir un código más limpio.

Haga un uso liberal de min-height

Para aquellos elementos que no necesitan un tamaño receptivo sino una altura fija, considere usar min-height . Esto podría ser para un encabezado de altura fija , por ejemplo, y podemos tener diferentes encabezados para los diferentes puntos de interrupción utilizando consultas de medios como de costumbre:

 header { min-height: 50px; } @media (min-width: 600px) { header { min-height: 200px; } }
 <header> ... </header>

Por supuesto, lo mismo se aplica a min-width para elementos colocados horizontalmente, pero normalmente es la altura la que causa los problemas de CLS.

Una técnica más avanzada para el contenido inyectado y los selectores de CSS avanzados es apuntar cuando el contenido esperado aún no se ha insertado. Por ejemplo, si tuviera el siguiente contenido:

 <div class="container"> <div class="main-content">...</div> </div>

Y se inserta un div adicional a través de JavaScript:

 <div class="container"> <div class="additional-content">.../div> <div class="main-content">...</div> </div>

Luego, podría usar el siguiente fragmento de código para dejar espacio para contenido adicional cuando el div main-content se represente inicialmente.

 .main-content:first-child { margin-top: 20px; }

Este código en realidad creará un cambio al elemento main-content ya que el margen cuenta como parte de ese elemento, por lo que parecerá cambiar cuando se elimine (aunque en realidad no se mueva en la pantalla). Sin embargo, al menos el contenido debajo de él no se cambiará, por lo que debería reducir CLS.

Alternativamente, puede usar el pseudo-elemento ::before para agregar el espacio para evitar el cambio en el elemento main-content también:

 .main-content:first-child::before { content: ''; min-height: 20px; display: block; }

Pero con toda honestidad, la mejor solución es tener el div en el HTML y hacer uso de min-height en eso.

Comprobar elementos alternativos

Me gusta usar la mejora progresiva para proporcionar un sitio web básico, incluso sin JavaScript cuando sea posible. Desafortunadamente, esto me atrapó recientemente en un sitio que mantengo cuando la versión alternativa que no es de JavaScript era diferente a cuando se activó JavaScript.

El problema se debió al botón de menú "Tabla de contenido" en el encabezado. Antes de que JavaScript se active, hay un enlace simple, diseñado para parecerse al botón que lo lleva a la página de Tabla de contenido. Una vez que JavaScript se activa, se convierte en un menú dinámico que le permite navegar directamente a cualquier página a la que desee ir desde esa página.

Capturas de pantalla de dos componentes de navegación de Tabla de contenido con el estilo de un botón. Con JavaScript esto abre un menú dinámico como se muestra en la segunda imagen.
Un componente de encabezado de tabla de contenido que inicialmente se representa como un enlace simple (arriba) y luego se mejora con JavaScript para que sea un menú dinámico (abajo). (Vista previa grande)

Usé elementos semánticos y, por lo tanto, usé un elemento ancla ( <a href="#table-of-contents"> ) para el enlace alternativo, pero lo reemplacé con un <button> para el menú dinámico basado en JavaScript. Estos se diseñaron para que se vieran iguales, ¡pero el enlace alternativo era un par de píxeles más pequeño que el botón!

Esto era tan pequeño, y el JavaScript generalmente se activaba tan rápido, que no me había dado cuenta de que estaba apagado. Sin embargo, Chrome lo notó al calcular el CLS y, como estaba en el encabezado, desplazó la página completa un par de píxeles hacia abajo. Así que esto tuvo un gran impacto en el puntaje de CLS, lo suficiente como para colocar todas nuestras páginas en la categoría "Necesita mejorar".

Esto fue un error de mi parte, y la solución fue simplemente sincronizar los dos elementos (también podría haberse remediado estableciendo una min-height en el encabezado como se mencionó anteriormente), pero me confundió un poco. Estoy seguro de que no soy el único que cometió este error, así que tenga en cuenta cómo se representa la página sin JavaScript. ¿No cree que sus usuarios deshabilitan JavaScript? Todos sus usuarios no son JS mientras descargan su JS.

Las fuentes web provocan cambios en el diseño

Las fuentes web son otra causa común de CLS debido a que el navegador inicialmente calcula el espacio necesario en función de la fuente alternativa y luego lo vuelve a calcular cuando se descarga la fuente web. Por lo general, el CLS es pequeño, siempre que se use una fuente alternativa de tamaño similar, por lo que a menudo no causan un problema suficiente para fallar en Core Web Vitals, pero pueden ser molestos para los usuarios.

Dos capturas de pantalla de un artículo de Smashing Magazine con diferentes fuentes. El texto tiene un tamaño notablemente diferente y puede caber una oración adicional cuando se usan las fuentes web.
Artículo de Smashing Magazine con fuente alternativa y con fuentes web completas. (Vista previa grande)

Desafortunadamente, incluso precargar las fuentes web no ayudará aquí, ya que, si bien eso reduce el tiempo de uso de las fuentes alternativas (por lo que es bueno para el rendimiento de carga, LCP), todavía lleva tiempo recuperarlas , por lo que las fuentes alternativas aún se utilizarán. por el navegador en la mayoría de los casos, por lo que no evita CLS. Dicho esto, si sabe que se necesita una fuente web en la página siguiente (digamos que está en una página de inicio de sesión y sabe que la página siguiente usa una fuente especial), puede obtenerla previamente.

Para evitar por completo los cambios de diseño inducidos por las fuentes , por supuesto, no podríamos usar fuentes web en absoluto, incluido el uso de fuentes del sistema en su lugar, o el uso font-display: optional para no usarlas si no se descargan a tiempo para el renderizado inicial. Pero ninguno de esos es muy satisfactorio, para ser honesto.

Otra opción es asegurarse de que las secciones tengan el tamaño adecuado (p. ej., con min-height ), de modo que, si bien el texto en ellas puede cambiar un poco, el contenido que se encuentra debajo no se empujará hacia abajo incluso cuando esto suceda. Por ejemplo, establecer una min-height en el elemento <h1> podría evitar que todo el artículo se desplace hacia abajo si se cargan fuentes un poco más altas, siempre que las diferentes fuentes no generen una cantidad diferente de líneas. Esto reducirá el impacto de los cambios, sin embargo, para muchos casos de uso (por ejemplo, párrafos genéricos) será difícil generalizar una altura mínima.

Lo que más me entusiasma para resolver este problema son los nuevos descriptores de fuentes CSS que le permiten ajustar más fácilmente las fuentes alternativas en CSS:

 @font-face { font-family: 'Lato'; src: url('/static/fonts/Lato.woff2') format('woff2'); font-weight: 400; } @font-face { font-family: "Lato-fallback"; size-adjust: 97.38%; ascent-override: 99%; src: local("Arial"); } h1 { font-family: Lato, Lato-fallback, sans-serif; }

Antes de esto, el ajuste de la fuente alternativa requería usar la API de carga de fuentes en JavaScript, que era más complicado, pero esta opción que saldrá muy pronto finalmente puede brindarnos una solución más fácil que es más probable que gane tracción. Consulte mi artículo anterior sobre este tema para obtener más detalles sobre esta próxima innovación y más recursos al respecto.

Plantillas iniciales para páginas renderizadas del lado del cliente

Muchas páginas renderizadas del lado del cliente, o aplicaciones de una sola página, renderizan una página básica inicial usando solo HTML y CSS, y luego "hidratan" la plantilla después de que JavaScript se descarga y ejecuta.

Es fácil que estas plantillas iniciales no estén sincronizadas con la versión de JavaScript, ya que se agregan nuevos componentes y funciones a la aplicación en JavaScript, pero no se agregan a la plantilla HTML inicial que se representa primero. Esto luego causa CLS cuando estos componentes son inyectados por JavaScript.

Así que revise todas sus plantillas iniciales para asegurarse de que sigan siendo buenos marcadores de posición iniciales. Y si la plantilla inicial consta de <div> vacíos, utilice las técnicas anteriores para asegurarse de que tengan el tamaño adecuado para tratar de evitar cambios.

Además, el div inicial que se inyecta con la aplicación debe tener una min-height para evitar que se represente con una altura 0 inicialmente antes de que se inserte la plantilla inicial.

 <div></div>

Siempre que la min-height sea mayor que la mayoría de las ventanas gráficas , esto debería evitar cualquier CLS para el pie de página del sitio web, por ejemplo. CLS solo se mide cuando está en la ventana gráfica y, por lo tanto, afecta al usuario. De forma predeterminada, un div vacío tiene una altura de 0px, así que dale una min-height que esté más cerca de la altura real cuando se cargue la aplicación.

Asegúrese de que las interacciones del usuario se completen en 500 ms

Las interacciones del usuario que hacen que el contenido cambie se excluyen de las puntuaciones de CLS. Estos están restringidos a 500 ms después de la interacción. Entonces, si hace clic en un botón y realiza un procesamiento complejo que toma más de 500 ms y luego genera contenido nuevo, entonces su puntaje CLS se verá afectado.

Puede ver si el turno se excluyó en Chrome DevTools usando la pestaña Rendimiento para registrar la página y luego buscando los turnos como se muestra en la siguiente captura de pantalla. Abra DevTools, vaya a la muy intimidante (¡pero muy útil una vez que lo domine!) Pestaña de rendimiento y luego haga clic en el botón de grabación en la parte superior izquierda (encerrado en un círculo en la imagen a continuación) e interactúe con su página, y deje de grabar una vez completo.

Captura de pantalla de Chrome Dev Tools con un turno seleccionado y el Resumen de esto muestra que tuvo una entrada reciente y, por lo tanto, el turno no está incluido en el puntaje acumulativo.
Usar la pestaña Rendimiento en Chrome Dev Tools para ver si los turnos están excluidos debido a una entrada reciente. (Vista previa grande)

Verá una tira de película de la página en la que cargué algunos de los comentarios en otro artículo de Smashing Magazine, por lo que en la parte que he marcado con un círculo, puede distinguir los comentarios cargando y el pie de página rojo desplazado hacia abajo fuera de la pantalla. Más abajo en la pestaña Rendimiento , debajo de la línea Experiencia , Chrome colocará un cuadro rojizo-rosado para cada turno y cuando haga clic en él obtendrá más detalles en la pestaña Resumen a continuación.

Aquí puede ver que obtuvimos un puntaje masivo de 0.3359 , muy por encima del umbral de 0.1 por debajo del cual pretendemos estar, pero el puntaje acumulativo no ha incluido esto, porque la entrada reciente está configurada en Usos.

Garantizar que las interacciones solo cambien el contenido dentro de los límites de 500 ms en lo que intenta medir el Retraso de la primera entrada, pero hay casos en los que el usuario puede ver que la entrada tuvo un efecto (por ejemplo, se muestra una rueda giratoria de carga), por lo que FID es bueno, pero el contenido puede no se agregará a la página hasta después del límite de 500 ms, por lo que CLS es malo.

Idealmente, toda la interacción terminará en 500 ms, pero puede hacer algunas cosas para reservar el espacio necesario usando las técnicas anteriores mientras se lleva a cabo el procesamiento, de modo que si toma más de los mágicos 500 ms, entonces tiene ya manejó el turno y por lo tanto no será penalizado por ello. Esto es especialmente útil cuando se obtiene contenido de la red que podría ser variable y estar fuera de su control.

Otros elementos a tener en cuenta son las animaciones que tardan más de 500 ms y, por lo tanto, pueden afectar a CLS. Si bien esto puede parecer un poco restrictivo, el objetivo de CLS no es limitar la "diversión", sino establecer expectativas razonables de la experiencia del usuario y no creo que sea poco realista esperar que tarden 500 ms o menos. Pero si no está de acuerdo o tiene un caso de uso que quizás no hayan considerado, entonces el equipo de Chrome está abierto a recibir comentarios al respecto.

JavaScript síncrono

La técnica final que voy a discutir es un poco controvertida ya que va en contra de los consejos de rendimiento web bien conocidos, pero puede ser el único método en ciertas situaciones. Básicamente, si tiene contenido que sabe que va a causar cambios, entonces una solución para evitar los cambios es no renderizarlo hasta que se establezca.

El HTML a continuación ocultará el div inicialmente, luego cargará un JavaScript que bloquea el procesamiento para completar el div y luego lo mostrará. Como JavaScript bloquea la representación, no se representará nada debajo de esto (incluido el segundo bloque de style para mostrarlo) y, por lo tanto, no se incurrirá en cambios.

 <style> .cls-inducing-div { display: none; } </style> <div class="cls-inducing-div"></div> <script> ... </script> <style> .cls-inducing-div { display: block; } </style>

Es importante alinear el CSS en el HTML con esta técnica, para que se aplique en orden. La alternativa es mostrar el contenido con JavaScript, pero lo que me gusta de la técnica anterior es que aún muestra el contenido incluso si JavaScript falla o el navegador lo apaga.

Esta técnica también se puede aplicar con JavaScript externo, pero esto causará más retraso que un script en línea a medida que se solicita y descarga el JavaScript externo. Ese retraso se puede minimizar cargando previamente el recurso de JavaScript para que esté disponible más rápido una vez que el analizador llegue a esa sección de código:

 <head> ... <link rel="preload" href="cls-inducing-javascript.js" as="script"> ... </head> <body> ... <style> .cls-inducing-div { display: none; } </style> <div class="cls-inducing-div"></div> <script src="cls-inducing-javascript.js"></script> <style> .cls-inducing-div { display: block; } </style> ... </body>

Ahora, como digo, estoy seguro de que esto hará que algunas personas de rendimiento web se estremezcan, ya que el consejo es usar async, defer o el type="module" más nuevo (que son defer -ed por defecto) en JavaScript específicamente para evitar el bloqueo render , ¡mientras que estamos haciendo lo contrario aquí! Sin embargo, si el contenido no se puede predeterminar y va a causar cambios bruscos, entonces no tiene mucho sentido renderizarlo antes.

Usé esta técnica para un banner de cookies que se cargaba en la parte superior de la página y desplazaba el contenido hacia abajo:

Una captura de pantalla de una página web, donde el contenido se desplaza hacia abajo cuando se agrega un banner de cookies en la parte superior de la página.
Un aviso de cookies en la parte superior de la página u otro banner puede desplazar el contenido hacia abajo. (Vista previa grande)

Esto requería leer una cookie para ver si mostrar el banner de cookies o no y, si bien eso se podía completar en el lado del servidor, este era un sitio estático sin capacidad para alterar dinámicamente el HTML devuelto.

Los banners de cookies se pueden implementar de diferentes maneras para evitar CLS. Por ejemplo, colocándolos en la parte inferior de la página o superponiéndolos sobre el contenido, en lugar de desplazar el contenido hacia abajo. Preferimos mantener el contenido en la parte superior de la página, por lo que tuvimos que usar esta técnica para evitar los cambios. Hay varias otras alertas y pancartas que los propietarios de sitios pueden preferir que estén en la parte superior de la página por varias razones.

También utilicé esta técnica en otra página donde JavaScript mueve el contenido a las columnas "principal" y "aparte" (por razones que no mencionaré, no fue posible construir esto correctamente en el lado del servidor HTML). Ocultar nuevamente el contenido, hasta que JavaScript lo reorganizó, y solo luego mostrarlo, evitó los problemas de CLS que estaban arrastrando hacia abajo la puntuación de CLS de estas páginas. Y nuevamente, el contenido se muestra automáticamente incluso si JavaScript no se ejecuta por algún motivo y se muestra el contenido no modificado.

El uso de esta técnica puede afectar otras métricas (particularmente LCP y también First Contentful Paint) ya que está retrasando el renderizado y también potencialmente bloqueando el precargador de anticipación de los navegadores, pero es otra herramienta a considerar para aquellos casos en los que no existe otra opción.

Conclusión

El cambio de diseño acumulativo es causado por el cambio de contenido en las dimensiones, o por la inyección de contenido nuevo en la página debido a la ejecución tardía de JavaScript. En esta publicación, hemos discutido varios consejos y trucos para evitar esto. Me alegro de que el centro de atención de Core Web Vitals haya brillado sobre este irritante problema: durante demasiado tiempo, los desarrolladores web (y definitivamente me incluyo en esto) hemos ignorado este problema.

La limpieza de mis propios sitios web ha llevado a una mejor experiencia para todos los visitantes. Lo animo a que también revise sus problemas de CLS y, con suerte, algunos de estos consejos le serán útiles cuando lo haga. Quién sabe, ¡puede que incluso consigas llegar a la escurridiza puntuación CLS de 0 para todas tus páginas!

Más recursos

  • Artículos de Core Web Vitals aquí en Smashing Magazine, incluido el mío sobre Configuración de ancho y alto en imágenes, Medición de Core Web Vitals y Descriptores de fuentes CSS.
  • Documentación de Core Web Vitals de Google, incluida su página en CLS.
  • Más detalles sobre el cambio reciente a CLS y luego este cambio comenzó a actualizarse en varias herramientas de Google.
  • El registro de cambios de CLS que detalla los cambios en cada versión de Chrome.
  • La guía casi completa para el cambio de diseño acumulativo por Jess Peck.
  • Cambio de diseño acumulativo: Mida y evite la inestabilidad visual por Karolina Szczur.
  • Un generador de GIF de cambio de diseño para ayudar a generar demostraciones compartibles de CLS.