Cómo depurar cambios de diseño

Obtén información para identificar y corregir los cambios de diseño.

Katie Hempenius
Katie Hempenius

En la primera parte de este artículo, se analizan las herramientas para depurar los cambios de diseño, mientras que en la segunda parte, se analiza el proceso de pensamiento que se debe usar cuando se identifica la causa de un cambio de diseño.

API de Layout Instability

La API de Layout Instability es el mecanismo del navegador para medir y generar informes sobre los cambios de diseño. Todas las herramientas para debugging de cambios de diseño, incluidas DevTools, se compilan en la API de Layout Instability. Sin embargo, usar la API de Layout Instability directamente es una herramienta de depuración potente debido a su flexibilidad.

Uso

El mismo fragmento de código que mide el Cambio de diseño acumulado (CLS) también puede entregar para depurar los cambios de diseño. En el siguiente fragmento, se registra información sobre los cambios de diseño a la consola. Si inspeccionas este registro, obtendrás información sobre cuándo, dónde y cómo ocurrió un cambio de diseño.

let cls = 0;
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Cuando ejecutes esta secuencia de comandos, ten en cuenta lo siguiente:

  • La opción buffered: true indica que PerformanceObserver debe verificar el búfer de entrada de rendimiento del navegador en busca de entradas de rendimiento que se hayan creado antes de la inicialización del observador. Como resultado, PerformanceObserver informará cambios de diseño que ocurrieron antes y después de su inicialización. Ten esto en cuenta cuando inspecciones los registros de la consola. Un grupo inicial de cambios de diseño puede reflejar una lista de tareas pendientes de los informes, en lugar de la ocurrencia repentina de varios cambios de diseño.
  • Para evitar afectar el rendimiento, PerformanceObserver espera hasta que el subproceso principal esté inactivo para informar sobre los cambios de diseño. En consecuencia, según qué tan ocupado esté el subproceso principal, puede haber una pequeña demora entre el momento en que se produce un cambio de diseño y el momento en que se registra en la consola.
  • Esta secuencia de comandos ignora los cambios de diseño que se produjeron en un plazo de 500 ms después de la entrada del usuario y, por lo tanto, no se tienen en cuenta para la CLS.

La información sobre los cambios de diseño se informa con una combinación de dos APIs: las interfaces LayoutShift y LayoutShiftAttribution. Cada una de estas interfaces se explica con más detalle en las siguientes secciones.

LayoutShift

Cada cambio de diseño se informa a través de la interfaz LayoutShift. El contenido de una entrada se ve de la siguiente manera:

duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798

La entrada anterior indica un cambio de diseño durante el cual tres elementos del DOM cambiaron de posición. La puntuación de cambio de diseño de este cambio de diseño en particular fue 0.175.

Estas son las propiedades de una instancia de LayoutShift que son más relevantes para debugging los cambios de diseño:

Propiedad Descripción
sources La propiedad sources enumera los elementos del DOM que se movieron durante el cambio de diseño. Este array puede contener hasta cinco fuentes. En caso de que haya más de cinco elementos afectados por el cambio de diseño, se informan las cinco fuentes más grandes (medidas por el impacto en la estabilidad del diseño) del cambio de diseño. Esta información se informa a través de la interfaz LayoutShiftAttribution (que se explica con más detalle a continuación).
value La propiedad value informa la puntuación de cambio de diseño de un cambio de diseño en particular.
hadRecentInput La propiedad hadRecentInput indica si se produjo un cambio de diseño dentro de los 500 milisegundos posteriores a la entrada del usuario.
startTime La propiedad startTime indica cuándo se produjo un cambio de diseño. startTime se indica en milisegundos y se mide en relación con el momento en que se inició la carga de la página.
duration La propiedad duration siempre se establecerá en 0. Esta propiedad se hereda de la interfaz PerformanceEntry (la interfaz LayoutShift extiende la interfaz PerformanceEntry). Sin embargo, el concepto de duración no se aplica a los eventos de cambio de diseño, por lo que se establece en 0. Para obtener información sobre la interfaz PerformanceEntry, consulta la especificación.

LayoutShiftAttribution

La interfaz LayoutShiftAttribution describe un solo cambio de un solo elemento DOM. Si varios elementos cambian durante un cambio de diseño, la propiedad sources contiene varias entradas.

Por ejemplo, el siguiente JSON corresponde a un cambio de diseño con una fuente: el cambio hacia abajo del elemento del DOM <div id='banner'> de y: 76 a y:246.

// ...
  "sources": [
    {
      "node": "div#banner",
      "previousRect": {
        "x": 311,
        "y": 76,
        "width": 4,
        "height": 18,
        "top": 76,
        "right": 315,
        "bottom": 94,
        "left": 311
      },
      "currentRect": {
        "x": 311,
        "y": 246,
        "width": 4,
        "height": 18,
        "top": 246,
        "right": 315,
        "bottom": 264,
        "left": 311
      }
    }
  ]

La propiedad node identifica el elemento HTML que cambió. Si colocas el cursor sobre esta propiedad en DevTools, se destacará el elemento de página correspondiente.

Las propiedades previousRect y currentRect informan el tamaño y la posición del nodo.

  • Las coordenadas x y y informan la coordenada X y la coordenada Y, respectivamente de la esquina superior izquierda del elemento.
  • Las propiedades width y height informan el ancho y la altura, respectivamente, del elemento.
  • Las propiedades top, right, bottom y left informan los valores de las coordenadas x o y que corresponden al borde determinado del elemento. En otras palabras, el valor de top es igual a y; el valor de bottom es igual a y+height.

Si todas las propiedades de previousRect se establecen en 0, significa que el elemento cambió a la vista. Si todas las propiedades de currentRect se establecen en 0, significa que el elemento está fuera de la vista.

Uno de los aspectos más importantes que debes comprender cuando se interpretan estos resultados es que los elementos enumerados como fuentes son aquellos que cambiaron durante el cambio de diseño. Sin embargo, es posible que estos elementos solo estén relacionados de forma indirecta con la "causa raíz" de la inestabilidad del diseño. Estos son algunos ejemplos.

Ejemplo 1

Este cambio de diseño se informaría con una fuente: el elemento B. Sin embargo, la causa raíz de este cambio de diseño es el cambio de tamaño del elemento A.

Ejemplo que muestra un cambio de diseño causado por un cambio en las dimensiones del elemento

Ejemplo 2

El cambio de diseño en este ejemplo se informaría con dos fuentes: el elemento A y el elemento B. La causa raíz de este cambio de diseño es el cambio en la posición del elemento A.

Ejemplo de un cambio de diseño causado por un cambio en la posición del elemento

Ejemplo 3

El cambio de diseño en este ejemplo se informaría con una fuente: el elemento B. Cambiar la posición del elemento B generó este cambio de diseño.

Ejemplo de un cambio de diseño causado por un cambio en la posición del elemento

Ejemplo 4

Aunque el elemento B cambia de tamaño, no hay un cambio de diseño en este ejemplo.

Ejemplo que muestra un elemento que cambia de tamaño, pero que no provoca un cambio de diseño

Consulta una demo de cómo la API de Layout Instability informa los cambios en el DOM.

Herramientas para desarrolladores

Panel de rendimiento

En el panel Experiencia del panel Rendimiento de Herramientas para desarrolladores, se muestran todos los cambios de diseño que ocurren durante un registro de rendimiento determinado, incluso si ocurren dentro de los 500 ms posteriores a una interacción del usuario y, por lo tanto, no se registran para CLS. Si colocas el cursor sobre un cambio de diseño en particular en el panel Experience, se destacará el elemento del DOM afectado.

Captura de pantalla de un cambio de diseño que se muestra en el panel de red de Herramientas para desarrolladores

Para obtener más información sobre el cambio de diseño, haz clic en él y, luego, abre el panel lateral Resumen. Los cambios en las dimensiones del elemento se enumeran con el formato [width, height]; los cambios en la posición del elemento se enumeran con el formato [x,y]. La propiedad Had recent input indica si se produjo un cambio de diseño dentro de los 500 ms de una interacción del usuario.

Captura de pantalla de la pestaña &#39;Summary&#39; de Herramientas para desarrolladores para un cambio de diseño

Para obtener información sobre la duración de un cambio de diseño, abre la pestaña Registro de eventos. La duración de un cambio de diseño también se puede aproximar si se busca la longitud del rectángulo rojo de cambio de diseño en el panel Experiencia.

Captura de pantalla de la pestaña &quot;Registro de eventos&quot; de Herramientas para desarrolladores para un cambio de diseño

Para obtener más información sobre el uso del panel Rendimiento, consulta la Referencia de análisis de rendimiento.

Destaca las regiones de cambio de diseño

Destacar las regiones de cambio de diseño puede ser una técnica útil para obtener una idea rápida y sencilla de la ubicación y el tiempo de los cambios de diseño que se producen en una página.

Para habilitar las regiones de cambio de diseño en DevTools, ve a Configuración > Más herramientas > Renderización > Regiones de cambio de diseño y, luego, actualiza la página que deseas depurar. Las áreas de cambio de diseño se destacarán brevemente en púrpura.

Proceso de pensamiento para identificar la causa de los cambios de diseño

Puedes usar los pasos que se indican a continuación para identificar la causa de los cambios de diseño sin importar cuándo o cómo se produce. Estos pasos se pueden complementar con la ejecución de Lighthouse. Sin embargo, ten en cuenta que Lighthouse solo puede identificar los cambios de diseño que se produjeron durante la carga inicial de la página. Además, Lighthouse también puede proporcionar sugerencias solo para algunas causas de los cambios de diseño, por ejemplo, elementos de imagen que no tienen ancho ni altura explícitos.

Identifica la causa de un cambio de diseño

Los siguientes eventos pueden causar cambios de diseño:

  • Cambios en la posición de un elemento DOM
  • Cambios en las dimensiones de un elemento DOM
  • Inserción o eliminación de un elemento DOM
  • Animaciones que activan el diseño

En particular, el elemento DOM que antecede al elemento desplazado es el que tiene más probabilidades de involucrarse en "causar" el cambio de diseño. Por lo tanto, cuando investigues por qué se produjo un cambio de diseño, ten en cuenta lo siguiente:

  • ¿Cambió la posición o las dimensiones del elemento anterior?
  • ¿Se insertó o quitó un elemento del DOM antes del elemento desplazado?
  • ¿Se cambió explícitamente la posición del elemento desplazado?

Si el elemento anterior no causó el cambio de diseño, continúa la búsqueda considerando otros elementos anteriores y cercanos.

Además, la dirección y la distancia de un cambio de diseño pueden proporcionar sugerencias sobre la causa raíz. Por ejemplo, un cambio grande hacia abajo suele indicar la inserción de un elemento DOM, mientras que un cambio de diseño de 1 px o 2 px suele indicar la aplicación de estilos CSS en conflicto o la carga y aplicación de una fuente web.

Diagrama que muestra un cambio de diseño causado por un intercambio de fuentes
En este ejemplo, el intercambio de fuentes hizo que los elementos de página se desplazaran cinco píxeles hacia arriba.

Estos son algunos de los comportamientos específicos que causan eventos de cambio de diseño con mayor frecuencia:

Cambios en la posición de un elemento (que no se deben al movimiento de otro elemento)

Este tipo de cambio suele ser el resultado de lo siguiente:

  • Hojas de estilo que se cargan tarde o reemplazan los estilos declarados anteriormente.
  • Efectos de animación y transición

Cambios en las dimensiones de un elemento

Este tipo de cambio suele ser el resultado de lo siguiente:

  • Hojas de estilo que se cargan tarde o reemplazan los estilos declarados con anterioridad.
  • Imágenes y iframes sin los atributos width y height que se cargan después de que se renderiza su "ranura"
  • Bloques de texto sin atributos width o height que intercambian fuentes después de que se renderiza el texto.

La inserción o eliminación de elementos DOM

Esto suele deberse a lo siguiente:

  • Inserción de anuncios y otras incorporaciones de terceros
  • Inserción de banners, alertas y ventanas modales
  • Desplazamiento infinito y otros patrones de UX que cargan contenido adicional sobre el contenido existente

Animaciones que activan el diseño

Algunos efectos de animación pueden activar el diseño. Un ejemplo común de esto es cuando los elementos DOM se "animan" mediante el incremento de propiedades como top o left en lugar de usar la propiedad transform de CSS. Consulta Cómo crear animaciones de CSS de alto rendimiento para obtener más información.

Cómo reproducir cambios de diseño

No puedes corregir los cambios de diseño que no puedes reproducir. Una de las acciones más simples y, a la vez, más eficaces que puedes realizar para obtener una mejor idea de la estabilidad del diseño de tu sitio es dedicar de 5 a 10 minutos a interactuar con él con el objetivo de activar los cambios de diseño. Mientras haces esto, mantén la consola abierta y usa la API de inestabilidad de diseño para informar sobre los cambios de diseño.

Para los cambios de diseño difíciles de ubicar, considera repetir este ejercicio con diferentes dispositivos y velocidades de conexión. En particular, usar una velocidad de conexión más lenta puede facilitar la identificación de los cambios de diseño. Además, puedes usar una declaración debugger para facilitar los cambios de diseño.

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    if (!entry.hadRecentInput) {
      cls += entry.value;
      debugger;
      console.log('Current CLS value:', cls, entry);
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Por último, en el caso de los problemas de diseño que no son reproducibles durante el desarrollo, considera usar la API de inestabilidad de diseño junto con la herramienta de registro de frontend que prefieras para recopilar más información sobre estos problemas. Consulta el código de ejemplo para saber cómo hacer un seguimiento del elemento desplazado más grande de una página.