A todos nosotros nos ha pasado. Estamos utilizando una aplicación web o móvil, vamos a pulsar sobre un botón o enlace, para ejecutar alguna acción, y en ese mismo instante el contenido se actualiza, por lo que quedamos pulsando sobre cualquier otro elemento y no sabemos dónde quedó el botón o enlace que íbamos a pulsar.
A nivel de diseño y desarrollo centrado en usuario, estos tipos de errores comunes se pueden medir a través de una métrica conocida como “Cummulative Layout Shift (CLS)”, que básicamente se define como:
(…) una medida de la ráfaga más grande de las puntuaciones de cambio de diseño para cada cambio de diseño inesperado que se produce durante toda la vida útil de una página.
Se produce un cambio de diseño cada vez que un elemento visible cambia su posición de un fotograma renderizado al siguiente.
Esta métrica categoriza el renderizado de contenido en tres tipos:
- Bueno: CLS por debajo de 0.1.
- Mejorable: CLS entre 0.1-0.25.
- Necesita mejorar: CLS por encima de 0.25.
De forma general, si el contenido dentro un marco de vista cambia completamente, la métrica de CLS sería de 1.0.
#.¿Por qué ocurre usualmente el cambio de contenido?
Usualmente el cambio de contenido (y su posición) ocurre cuando realizamos una carga asíncrona de los contenidos de una aplicación. Esto es cada vez más normal al utilizar librerías como React, Vue o Svelte, ya que el contenido del sitio es reactivo a la interacción de usuario, por lo que la carga de este contenido dependerá en ciertos estados.
Pongamos un ejemplo práctico, utilizando React:
Para este ejemplo, tenemos un pequeño carrito de compra. Este carrito de compra busca la orden (que para temas prácticos es un simple timer) y luego de 4 segundos muestra la tabla con la lista. Nada complejo.
Si notamos con detalle, la tabla, luego de ser llenada, va a desplazar al botón de “Poner Órden” para abajo, por lo que la experiencia del usuario puede verse afectada al mover el contenido.
#.¿Qué podemos hacer para mejorar esta métrica a la hora de desarrollar nuestras aplicaciones?
A la hora de desarrollar aplicaciones centradas en usuario, debemos primero colaborar estréchamente con el diseñador de intefaces y de experiencia de usuario y asegurarnos que el diseño considere casos como el anterior.
Si utilizamos el caso anterior, tenemos dos opciones, las cuales son aplicables para casi todos los casos:
#.Técnica 1: Dejar que crezca el contenido, pero posicionar los elementos de acción fuera de este área
Esta opción es usualmente la más simple y más fácil de llevar a cabo. La solución, utilizando el ejemplo anterior, sería mover el botón de “Poner Órden” por encima de cualquier contenido que pueda actualizarse en el futuro.
De este modo, no nos corremos el riesgo de que la posición del elemento de acción varíe con el tiempo.
Esta opción es muy utilizada en interfaces móviles, por ejemplo, cuando posicionamos los elementos accionadores ya sea en el header o footer del marco de vista.
#.Técnica 2: Guardar el espacio mientras se cargue y hacer que el espacio guardado sea estático
Para esta otra opción, la solución es un tanto distinta y podemos utilizar algunos patrones sencillos. De igual forma, requerimos más uso de estilos para asegurarnos que la experiencia no se vea afectada.
Por ejemplo, podríamos configurar un espacio máximo para la tabla de productos, agregar algún tipo de cargador (un Loading box, o los hoy tan comunes Skeleton Screens) y utilizar scrolls únicamente para este área del contenido. De igual forma podemos utilizar Placeholders, ya sea en forma de texto o que simplemente se asegure de respetar el mismo área una vez el contenido es cargado.
Por ejemplo, si aplicamos esta opción y con un poco uso de CSS, podemos lograr algo como lo siguiente:
En este ejemplo ajustado veremos que realizamos los siguientes cambios a nivel de código:
- Configuramos un
height
estático para el área donde pondremos el contenido. - De igual manera utilizamos
overflow: scroll
, por si el contenido crece. De esta forma, si el contenido es mayor al espacio que guardamos, el contenido inferior no se verá afectado en su posición. - Si aún se está realizando la carga, mostramos un texto de
"Cargando ..."
. Esto es para ilustrar el concepto de Placeholders. Lo correcto sería mostrar contenido similar al que va a cargarse o utilizar algo como un Skeleton Screen.
⚠️ Este es un ejemplo meramente ilustrativo de la técnica. El resultado es un poco pobre, pero con esto podemos entender una forma fácil de atacar en una situación similar.
De hecho, en el último punto, podríamos hacer un esfuerzo aún mayor y solo encargarnos de llenar las partes del carrito que realmente van a variar, por ejemplo los montos totales y la lista de artículos. Eso beneficiaría aún más a tener una mejor medida de CLS.
Así que este ejemplo lo podríamos mejorar realizando algo como lo siguiente:
En este caso, solo alteramos la parte realmente dinámica del contenido, como la lista de productos o el desglose del carrito de compra hasta ese momento. De igual forma separamos el espacio mínimo mientras carga la información.
Aún así, ninguna de estas dos técnicas serán efectivas para mejorar la experiencia de usuario si la carga y renderizado demora más allá de 500ms, por lo que es extremadamente importante poder acelerar la carga del contenido como primera medida.