Layout Shift causado por transiciones CSS

Aprende a encontrar y eliminar transiciones CSS que crean layout shifts

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-07

Layout Shift causado por transiciones CSS: comprender y mitigar el impacto

Los Cumulative Layout Shifts causados por transiciones CSS a menudo ocurren temprano durante la fase de carga de la página. Estos layout shifts no ocurren de manera consistente lo que los hace difíciles de depurar.

Comprendiendo las transiciones CSS:

Las transiciones CSS son una herramienta poderosa para animar el cambio de una propiedad a lo largo del tiempo. Se utilizan comúnmente para efectos como desvanecimiento, deslizamiento y escalado de elementos en una página web. Los desarrolladores pueden definir efectos de transición especificando la propiedad a transicionar, la duración de la transición y la función de temporización que gobierna la aceleración de la transición.

Las transiciones pueden tener una propiedad, duración, timing-function y un delay. La forma abreviada de una transición se ve así:

/* property | duration | timing-function | delay */
transition: margin-right 4s ease-in-out 1s;

Layout Shifts: la consecuencia no deseada:

Los layout shifts ocurren cuando los elementos de una página web cambian de posición o tamaño, haciendo que otros elementos se redistribuyan y el diseño general de la página se desplace. Aunque las transiciones CSS están diseñadas para proporcionar animaciones fluidas, pueden desencadenar inadvertidamente layout shifts, lo que genera una experiencia de usuario desconcertante y disruptiva. Las causas más comunes de layout shifts durante las transiciones CSS incluyen cambios en las dimensiones, la posición o la visibilidad de los elementos.

Los Cumulative Layout Shifts causados por transiciones CSS generalmente ocurren cuando un elemento above-the-fold como un menú de navegación transiciona de su primer estado (sin estilos) a su estado final (con estilos o incluso oculto). Esto suele ser una consecuencia no deseada de propiedades de transición demasiado amplias. Por ejemplo, una entrada de menú solo debería transicionar el color de fondo y en lugar de la propiedad de transición 'background-color' se ha elegido 'all'. Esto provocará no solo una transición de fondo sino en algunos casos también una transición de width, height o incluso visibility durante la carga de la página.

Observa el ejemplo a continuación. Esto demuestra un layout shift causado por transiciones CSS que ocurren durante la fase de carga de una página. Desafortunadamente veo este patrón todo el tiempo y encontrar y solucionar este tipo de problemas puede ser difícil.

Encontrar y corregir transiciones CSS:

Para encontrar y corregir todos los layout shifts causados por transiciones CSS necesitamos hacer una prueba rápida. Primero necesitamos encontrar todas las transiciones CSS. Una vez hecho esto, necesitamos asegurarnos de que la transición no cambie la posición (width, height, margin, padding, visibility) de un elemento. Podemos hacer esto modificando o deshabilitando estas transiciones. Finalmente, podemos probar el impacto de estos cambios y decidir de una vez por todas si las transiciones CSS están causando problemas de CLS. 

Consejo de Core Web Vitals: Los Cumulative Layout Shifts causados por transiciones CSS a menudo ocurren temprano durante la fase de carga de la página. Estos layout shifts no ocurren de manera consistente, lo que los hace difíciles de depurar. ¡Ralentizar tu red emulando un dispositivo móvil y deshabilitando tu caché facilitará encontrarlos! 

Paso 1: Encontrar transiciones CSS

Encontrar transiciones CSS se puede hacer manualmente: inspecciona todas las hojas de estilo y busca la palabra 'transition'. Eso no debería llevar más de 10 minutos de trabajo, ¡pero hay una forma mejor! Simplemente pega este fragmento de código en la consola y presiona enter

(() => {
 
  let nodeTable = [];
  let nodeArray = [];

  // Get the name of the node
  function getName(node) {
    const name = node.nodeName;
    return node.nodeType === 1
      ? name.toLowerCase()
      : name.toUpperCase().replace(/^#/, '');
  }

  // Get the selector
  const getSelector = (node) => {
    let sel = '';

    try {
      while (node && node.nodeType !== 9) {
        const el = node;
        const part = el.id
          ? '#' + el.id
          : getName(el) +
          (el.classList &&
            el.classList.value &&
            el.classList.value.trim() &&
            el.classList.value.trim().length
            ? '.' + el.classList.value.trim().replace(/\s+/g, '.')
            : '');
        if (sel.length + part.length > (100) - 1) return sel || part;
        sel = sel ? part + '>' + sel : part;
        if (el.id) break;
        node = el.parentNode;
      }
    } catch (err) {
      // Do nothing...
    }
    return sel;
  };

  const getNodesWithTransition = (node) => {

    // Get the computed style
    let cs = window.getComputedStyle(node);
    let tp = cs['transition-property'];
    let td = cs['transition-duration'];

    // If there is a transition, add it to the table
    if (tp !== '' && tp !== 'none' && td != '0s') {
      nodeTable.push({ selector: getSelector(node), transition: cs['transition'] });
      nodeArray.push(node);
    }

    // Recursively call this function for each child node
    for (let i = 0; i < node.children.length; i++) {
      getNodesWithTransition(node.children[i]);
    }
  }

  // find all transitions
  getNodesWithTransition(document.body);

  // Display the results in the console
  console.log('%cReadable table of selectors and their transitions', 'color: red; font-weight: bold;');
  console.table(nodeTable);

  console.log('%cNodeList for you to inspect (harder to read but more info)', 'color: red; font-weight: bold;');
  console.log(nodeArray);


  // styles to temporarity override the transitions
  let selectors = nodeTable.map((item) => item.selector).join(', ');

  console.log('%cSpecific CSS to disable all transitions on this page', 'color: red; font-weight: bold;');
  console.log(`<style>${selectors}{transition-property: none !important;}</style>`);
  
  console.log('%cGlobal CSS to disable all transitions on this page (not suggested on production)', 'color: red; font-weight: bold;');
  console.log(`<style>*{transition-property: none !important;}</style>`);

})()

Te mostrará una tabla con todas las transiciones, los elementos en los que están trabajando y más detalles sobre las transiciones.

cls snippet table

Para encontrar layout shifts necesitamos buscar propiedades de transición como width,height, margin,paddingtransform, display y especialmente all (ya que all incluye todas las propiedades de transición válidas)

Paso 2: Modificar transiciones CSS

El fragmento de JavaScript anterior mostrará todas las transiciones además de proporcionar código de ejemplo sobre cómo deshabilitar esas transiciones. Para pruebas rápidas sugiero tomar el camino fácil y deshabilitar todas las transiciones con una simple línea de código CSS

<style>*{transition-property: none !important;}</style>

Por supuesto, para entornos en producción se requiere un poco más de finura. Elimina cuidadosamente solo las transition-properties innecesarias por cada selector. Por ejemplo, cambia #button{transition: all .2s} por  #button{transition: background-color .2s}

Paso 3: Medir el cambio en layout shift

El siguiente y último paso es medir el impacto. Puedes usar mi extensión de Chrome Core Web Vitals Visualizer o una herramienta RUM como CoreDash para medir el impacto real de estos cambios de código.

layout shift transition measured by coredash


Otras buenas prácticas para transiciones:

  1. Preferir la aceleración GPU: Utilizar la aceleración GPU para transiciones CSS puede descargar la carga de trabajo de renderizado del CPU al GPU. Esto se puede lograr asegurándose de que las propiedades que se transicionan sean propicias para la aceleración GPU, como opacity y transform.
  2. Usar la propiedad “will-change”: La propiedad CSS will-change informa al navegador que un elemento específico probablemente cambiará, permitiéndole optimizar el renderizado en consecuencia. 
  3. Asegurar dimensiones consistentes: Para prevenir layout shifts causados por cambios en las dimensiones, asegúrate de que los elementos tengan dimensiones consistentes antes y después de la transición. Esto puede implicar establecer dimensiones explícitas, usar valores basados en porcentajes o emplear técnicas como cajas de relación de aspecto.
  4. Optimizar funciones de temporización: La elección de la función de temporización puede impactar significativamente la percepción de fluidez durante una transición. Ten en cuenta los patrones de aceleración y desaceleración, y considera usar ease-in-out o funciones cubic bezier personalizadas para una sensación más natural.

Ask AI why your INP spiked.

CoreDash is the only RUM tool with MCP support. Connect it to your AI agent and query your Core Web Vitals data in natural language. No more clicking through dashboards.

See How It Works
Layout Shift causado por transiciones CSSCore Web Vitals Layout Shift causado por transiciones CSS