Cómo detectar y corregir problemas de Cumulative Layout Shift (CLS)
Aprende a detectar y corregir todos los problemas de Cumulative Layout Shift con datos de RUM, Chrome DevTools y fixes específicos de CSS y HTML.
Compartir
Cómo detectar y corregir problemas de Cumulative Layout Shift (CLS)
Esta página forma parte de nuestra serie sobre Cumulative Layout Shift (CLS). El CLS mide la estabilidad visual de la página registrando los movimientos inesperados de contenido. Una buena puntuación de CLS está por debajo de 0,1; por encima de 0,25 se considera mala. Si es tu primera vez con el CLS, empieza por la página central de CLS para conocer la fórmula, los umbrales y el funcionamiento de las session windows.
El CLS es la Core Web Vital con mejores resultados. Según el 2025 Web Almanac, el 72% de los sitios web supera el CLS a nivel global. Suena genial, hasta que te das cuenta de que la mayoría de los desarrolladores nunca ve problemas de CLS en su propia máquina. Los desplazamientos ocurren con visitantes primerizos en conexiones lentas. Para cuando lo compruebas en DevTools con la caché caliente, todo se ve bien. Justo eso hace que depurar el CLS sea tan complicado.
Esta guía se basa en el proceso paso a paso exacto que uso en mis consultorías de CLS. Primero datos de CrUX y RUM, validar en Chrome y luego escribir el fix.
Última revisión por Arjen Karel en marzo de 2026
CONSEJO SOBRE CLS: el CLS se mide en session windows, no como un total acumulado. El navegador agrupa los layout shifts en sesiones (máximo 5 segundos, con pausas de 1 segundo entre desplazamientos) y la puntuación de CLS corresponde a la peor sesión. Una sola ráfaga de desplazamientos al cargar la página puede hacer que suspendas el CLS, aunque el resto de la visita sea completamente estable.
Paso 1: comprueba el CLS en Search Console
Antes de cambiar nada, confirma que realmente tienes un problema de CLS. Entra en Google Search Console, ve a Core Web Vitals y revisa tanto móvil como desktop.
Si Google marca URLs con "CLS issue: more than 0.25" o "CLS issue: more than 0.1", tienes la confirmación del Chrome User Experience Report (CrUX) de que usuarios reales experimentan layout shifts en tu sitio.
A diferencia de LCP e INP, donde la potencia de cálculo y la velocidad de red son determinantes, los problemas de CLS pueden depender del dispositivo o del tamaño de pantalla. Cuando un mismo problema afecta a móvil y a desktop (imágenes sin dimensiones, font swaps, contenido inyectado), desktop puede registrar un valor de CLS mucho mayor debido al tamaño de la pantalla (porque puede verse afectada una porción mayor del viewport visible). Search Console agrupa las URLs: te dice qué tipos de página están afectados, pero no qué elementos se desplazan. Para eso necesitas Real User Monitoring.

Paso 2: identifica problemas de CLS con datos de RUM
Search Console confirma que el problema existe, pero apenas da información para actuar. Necesitas saber qué elementos se desplazan, en qué páginas y en qué condiciones. Para eso necesitas una herramienta de RUM.
Creé CoreDash precisamente para responder a estas preguntas. Añades una sola etiqueta de script y empieza a recopilar datos de atribución de CLS de cada visitante real. El dato clave para depurar el CLS es el elemento que se desplaza: el nodo del DOM que realmente se movió. Sin esa información, estás depurando a ciegas.
Localiza los elementos que se desplazan
Empieza revisando los datos de CLS agrupados por elemento. En CoreDash, ve a la página de CLS y consulta la tabla ordenada por "CLS by Element". Esto muestra qué elementos provocan el mayor layout shift entre todos los visitantes. Haz clic en el peor de ellos para filtrar todas las métricas de las páginas donde se desplazó ese elemento.

Descubre qué páginas están afectadas
Tras filtrar por el elemento con mayor desplazamiento, revisa el desglose por URL. Los problemas de CLS pueden afectar a todo el sitio o solo a ciertas plantillas. Así sabrás si el CLS se concentra en tipos de página específicos: fichas de producto con galerías de imágenes, artículos de blog con bloques de anuncios o landing pages con animaciones en el hero. Saber qué páginas fallan te indica dónde poner el foco.
Compara visitantes nuevos con recurrentes
Esta es otra comprobación rápida que suelo hacer, y tiene más impacto de lo que la mayoría cree. El CLS por font swap solo ocurre cuando la fuente no está en caché. El CLS en imágenes provocado por width: auto solo ocurre cuando la imagen no está en la caché del navegador. Si el CLS es mucho peor en las primeras visitas, estás ante un desplazamiento dependiente de la caché. Como desarrollador, jamás lo verás en tu máquina a menos que desactives la caché (un consejo: desactiva siempre la caché de Chrome... pero esa es otra historia).
Comprueba los tipos de dispositivo y los tamaños de viewport
El CLS suele mostrar un patrón en móvil y desktop distinto al de LCP e INP. Los diseños responsive pueden introducir desplazamientos que solo aparecen con anchos y altos de viewport específicos. Un ad slot que da problemas en desktop tal vez ni siquiera esté en el viewport de móvil. Un menú de navegación puede animarse de forma distinta en breakpoints más pequeños. Agrupa los datos de CLS por tipo de dispositivo para saber dónde ocurren.
Paso 3: depura el CLS con Chrome
Los datos de RUM ya te han indicado qué elementos se desplazan y por qué. Ahora reproduce el problema en local y localiza la causa.
Usa la extensión Core Web Vitals Visualizer
La forma más rápida de ver los layout shifts es con la extensión de Chrome Core Web Vitals Visualizer. Carga la página, haz clic en el icono de la extensión y recarga. Cada layout shift se resalta con una capa de color que muestra con exactitud qué se movió y cuánto. Uso esto como primer paso antes de abrir el panel Performance, porque da una respuesta visual inmediata.

Replica las condiciones en Chrome y revisa las capturas de red
Los problemas de CLS suelen ser invisibles con la caché caliente. Abre DevTools, desactiva la caché en la pestaña Network y limita la conexión a "Slow 4G" (mi opción favorita: te mostrará el CLS provocado por race conditions). Ahora haz clic en el icono del engranaje y desactiva la caché (mientras DevTools esté abierto). Esto simula las condiciones que experimentan quienes visitan la página por primera vez. Ve a la pestaña Network y activa las capturas de pantalla (screenshots). Ahora recarga la página y observa los desplazamientos.

Usa el panel Performance de Chrome
La mayoría de los layout shifts son fáciles de ver cuando sabes cómo buscarlos, pero a veces se resisten. Ese es el momento de abrir Chrome DevTools (Ctrl+Shift+I) e ir al panel Performance para analizarlos a fondo. Pulsa Ctrl+Shift+E para recargar y grabar. En cuanto cargue la página, haz scroll arriba y abajo varias veces. Detén la grabación.
Busca la pista "Layout Shifts". Cada desplazamiento aparece como un bloque de color. Haz clic en un desplazamiento para ver:
- El nodo desplazado: el elemento del DOM que se movió
- La puntuación del desplazamiento: fracción de impacto multiplicada por fracción de distancia
- hadRecentInput: si hubo interacción del usuario antes del desplazamiento (los clics y toques tienen un margen de 500 ms, pero el scroll no)
Presta atención al momento en que ocurren los desplazamientos. Los desplazamientos durante la carga apuntan a imágenes sin dimensiones, font swaps o transiciones CSS. Los desplazamientos durante el scroll apuntan a animaciones activadas por scroll que usan propiedades de layout.

Prueba rápida: desactiva todas las transiciones
Las transiciones CSS que animan propiedades de layout son una causa traicionera de CLS: solo provocan desplazamientos durante la carga y cuesta reproducirlas. Pega este snippet en la consola, fuerza la recarga de la página con la caché desactivada y compara el CLS:
document.head.insertAdjacentHTML('beforeend',
'<style>*{transition-property:none!important}</style>'); Si el CLS baja tras desactivar las transiciones, has dado con la causa. Consulta la guía para depurar transiciones CSS para localizar las transiciones concretas que lo provocan.
Cómo medir el CLS con la Layout Instability API
La Layout Instability API ofrece acceso directo a cada layout shift en JavaScript. Es la misma API que usan internamente las herramientas de RUM:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
console.log('Layout shift:', {
value: entry.value,
sources: entry.sources?.map(s => ({
node: s.node,
previousRect: s.previousRect,
currentRect: s.currentRect
}))
});
}
}
});
observer.observe({ type: 'layout-shift', buffered: true }); El array sources muestra qué elementos se movieron. hadRecentInput descarta los desplazamientos esperados tras clics y toques. Para medir esto en producción, utiliza CoreDash u otra herramienta de RUM.
Paso 4: corrige los problemas de CLS
Ya sabes qué elementos se mueven y por qué. Toca corregirlos. El CLS no tiene fases secuenciales como el LCP. En su lugar, los layout shifts se dividen en distintas categorías según su causa. Estas son las más habituales, en el orden en que suelo encontrarlas durante las auditorías.
1. Imágenes, vídeos e iframes sin dimensiones
Es la causa principal de CLS en la web. Según el 2025 Web Almanac, el 62% de las páginas en móvil incluye al menos una imagen sin dimensiones. La solución: incluye siempre los atributos width y height en las etiquetas <img>, <video> e <iframe>.
<img src="hero.jpg" width="800" height="450" alt="Description">
<style>
img {
height: auto;
max-width: 100%;
}
</style> Cuidado con width: auto en el CSS. Esta sola declaración anula el cálculo de la relación de aspecto del navegador y provoca layout shifts aunque hayas definido width y height en el HTML. Lo he visto en decenas de sitios. Quien desarrolló la web hizo todo bien en el marcado, pero una regla global de CSS como img { width: auto; height: auto; max-width: 100%; } lo arruinó por completo. Para ver la explicación detallada, consulta cómo corregir el layout shift provocado por imágenes con auto-sizing. Si buscas una guía completa que cubre todas las causas de CLS relacionadas con imágenes y medios (vídeos, iframes, dirección de arte, imágenes responsive, lazy loading, placeholders), consulta cómo las imágenes y el contenido multimedia provocan layout shift.
2. Web font swaps
Cuando una fuente web carga y sustituye a la fuente fallback, la diferencia de tamaño genera un layout shift. El 2025 Web Almanac indica que solo el 11% de las páginas precarga fuentes web. Esto significa que la inmensa mayoría de los sitios es vulnerable al CLS por font swap.
La solución consta de dos partes. Primero, haz que la fuente fallback coincida con las dimensiones de la fuente web mediante metric overrides:
<style>
@font-face {
font-family: 'My Font Fallback';
src: local('Arial');
size-adjust: 105.2%;
ascent-override: 93%;
descent-override: 24%;
line-gap-override: 0%;
}
@font-face {
font-family: 'My Font';
src: url('/fonts/myfont.woff2') format('woff2');
font-display: swap;
}
body {
font-family: 'My Font', 'My Font Fallback', sans-serif;
}
</style> Usa un Fallback Font Generator para calcular los valores de override correctos para tu combinación de fuentes. Segundo, acelera la entrega: aloja tú mismo las fuentes, precarga el archivo de fuente crítico y usa WOFF2 con subsetting. Para una estrategia completa, consulta carga responsive de fuentes web y cómo garantizar que el texto siga visible durante la carga de fuentes web.
3. Animaciones y transiciones CSS
Según el 2025 Web Almanac, el 40% de las páginas en móvil ejecuta animaciones non-composited. Estas animan propiedades como width, height, top, left, margin y padding, que provocan un recálculo de layout en cada fotograma.
El culpable más habitual es transition: all. Cuando se define transition: all .3s ease, cualquier cambio de propiedad se anima, incluidas las de layout. Durante la carga de la página, los elementos que pasan de su estado sin estilos al estilizado generan layout shifts intermitentes y casi imposibles de reproducir de forma consistente. Veo este patrón todo el tiempo.
La solución: sustituye las propiedades que provocan layout por propiedades composited.
- Usa
transform: translateY()en lugar detop/bottom - Usa
transform: translateX()en lugar deleft/right - Usa
transform: scale()en lugar dewidth/height - Usa
opacityen lugar devisibilitycombinada con cambios de altura - Nunca uses
transition: all. Especifica la propiedad exacta:transition: background-color .2s ease
transform y opacity se ejecutan por completo en el compositor thread y nunca provocan layout. Para ver el proceso de depuración completo, consulta layout shift causado por transiciones CSS.
4. Anuncios, embeds y contenido inyectado dinámicamente
Los anuncios cargan tarde y empujan el contenido hacia abajo. Los banners de cookies aparecen y desplazan la página. Las peticiones AJAX inyectan contenido nuevo sin reservar espacio primero. Todos responden al mismo problema: aparece algo en la página que el navegador no conocía en el momento del render.
La solución para todos ellos es reservar espacio. Para los ad slots, define un min-height que coincida con el tamaño previsto del anuncio:
<style>
.ad-slot {
min-height: 250px;
contain: layout style;
}
@media (min-width: 600px) {
.ad-slot { min-height: 90px; }
}
</style> La declaración contain: layout style aísla el contenedor del anuncio del resto de la página. Para los banners de cookies, usa position: fixed para superponerlos en lugar de desplazar el contenido hacia abajo. Para el contenido AJAX, reserva espacio con min-height. No necesitas acertar al píxel: un descuadre de 50 px genera mucho menos CLS que un desplazamiento de 400 px por no haber reservado espacio.
Para embeds de terceros como YouTube, Google Maps y widgets de chat, aplica el patrón facade: muestra un placeholder estático y carga el embed real solo cuando el usuario interactúe con él. Cero CLS y cero recursos desperdiciados.
5. Layout shifts provocados por scroll
Esta es la causa de CLS que Lighthouse jamás detectará. Lighthouse no hace scroll en la página, de modo que los layout shifts provocados por scroll son totalmente invisibles en las pruebas de lab data. La única forma de encontrarlos es con datos de RUM o grabando una traza en el panel Performance mientras haces scroll manualmente.
El ejemplo más habitual es un encabezado hide-on-scroll que anima la propiedad top. Esto es lo que la mayoría de los desarrolladores no sabe: el scroll no se considera una interacción excluida en la especificación de Layout Instability. Los clics y toques tienen un margen de 500 ms. El scroll no. Todo layout shift provocado por el scroll cuenta para la puntuación de CLS.
La solución: usa transform: translateY() en lugar de top para cualquier animación asociada al scroll. Lo mismo se aplica a efectos parallax, barras de navegación que se comprimen y barras de progreso vinculadas al scroll. Si se mueve al hacer scroll, anímalo con transform. Para ver el tutorial completo con ejemplos en vídeo, consulta cómo las animaciones por scroll provocan CLS.
Checklist de soluciones rápidas
| Causa del CLS | Cómo detectarlo | Solución |
|---|---|---|
| Imágenes/vídeos sin dimensiones | Auditoría de «unsized images» en Lighthouse | Añade width y height; elimina width: auto del CSS |
| Web font swaps | RUM: el CLS solo empeora en la primera visita | Font metric overrides; preload de WOFF2; alojar fuentes en tu servidor |
| Transiciones CSS | Snippet de consola para listar todas las transiciones | Sustituye transition: all por propiedades específicas; usa transform/opacity |
| Anuncios con carga tardía | Atribución de RUM que muestra los contenedores del anuncio | min-height en ad slots; contain: layout style |
| Banners de consentimiento de cookies | Pico de CLS en la primera visita; banner en los datos de atribución | Usa una capa superpuesta con position: fixed en vez de desplazar el contenido |
| Animaciones por scroll | Traza de Performance durante el scroll; field CLS > lab CLS | Sustituye top/left/height por transform |
Guías relacionadas
- Cómo las imágenes y el contenido multimedia provocan layout shift: la guía completa sobre CLS por imágenes sin dimensiones, vídeos, iframes, dirección de arte, imágenes responsive, lazy loading y placeholders.
- Cómo corregir el layout shift provocado por imágenes con auto-sizing
- Layout shift causado por transiciones CSS
- Cómo las animaciones por scroll provocan CLS
- Cómo garantizar que el texto siga visible durante la carga de fuentes web
- Alojar Google Fonts en tu servidor
- Carga responsive de fuentes web
Para obtener una visión completa de todas las Core Web Vitals, visita el hub de Core Web Vitals o usa la Ultimate Core Web Vitals Checklist para auditar todo tu sitio.

¿Necesitas una web más rápida?
Soy Arjen y llevo 17 años arreglando webs lentas. Si te encuentras con problemas que no puedes resolver por tu cuenta, envíame tu URL y hablamos.
Envíame tu URL
¿Por qué no funciona nuestro fix?
A veces la CDN sigue sirviendo el HTML antiguo, o el fix se metió en la plantilla de desktop y el móvil usa otra. Envíame tu URL y el problema, y te respondo con varias opciones. Primero reviso tus field data, luego dedicamos una hora a tu web, y en menos de un día tienes mis notas por escrito. 350 € sin IVA.
Envíame tu URL¿No tienes desarrollador para hacer el fix? Hago el trabajo yo mismo, en una copia de tu web.