Cómo las imágenes y los medios causan Cumulative Layout Shift (y cómo solucionarlo)
La guía completa para prevenir CLS por imágenes, vídeos, iframes, imágenes adaptables e incrustaciones de medios

Cómo las imágenes y los medios causan Cumulative Layout Shift (y cómo solucionarlo)
El 2025 Web Almanac pone una cifra a lo que sigo viendo en el campo: el 62% de las páginas móviles tienen al menos una imagen sin ancho ni alto explícitos. Eso hace que los medios sin tamaño sean la causa número uno de Cumulative Layout Shift en la web. Y cada uno de estos cambios es prevenible con técnicas que han existido desde 2019.
Última revisión por Arjen Karel en marzo de 2026
Table of Contents!
- Cómo las imágenes y los medios causan Cumulative Layout Shift (y cómo solucionarlo)
- El navegador no sabe qué tamaño tiene tu imagen
- Cómo el ancho y el alto previenen el Cumulative Layout Shift
- Cosas que deshacen la solución
- Cuándo CSS aspect-ratio es la mejor opción
- Vídeos, iframes y SVGs
- Imágenes adaptables (Responsive images)
- Contenedores fijos, carruseles y contención
- Cómo encontrar el CLS de las imágenes
- Lista de verificación rápida para solucionar CLS
- Dónde se encuentra la web respecto al CLS de imágenes
- Guías relacionadas
- Preguntas respondidas sobre el CLS en imágenes y medios
El navegador no sabe qué tamaño tiene tu imagen
Cada cambio de diseño causado por una imagen se reduce a una sola cosa. El navegador no sabe cuánto espacio reservar antes de que la imagen se cargue.
Cuando el navegador encuentra una etiqueta <img> sin dimensiones, no se detiene hasta conocer las dimensiones de la imagen. No, simplemente reserva un espacio de 0x0 píxeles. Luego la imagen se descarga, el navegador recalcula el diseño y todo lo que está debajo de la imagen salta hacia abajo. Ese salto es tu CLS.

Cómo el ancho y el alto previenen el Cumulative Layout Shift
La única solución para un cambio de diseño es reservar el espacio correcto. La forma más fácil de hacerlo es simplemente establecer el ancho y el alto (intrínsecos) correctos de la imagen. En 2019 y 2020 todos los navegadores principales lanzaron una función que cambió cómo funcionan los atributos width y height. Los navegadores ahora los usan para calcular una relación de aspecto antes de que la imagen se descargue.
Cuando escribes esto:
<img src="hero.jpg" width="800" height="450" alt="Descripción">
El navegador genera esto internamente:
img[Attributes Style] {
aspect-ratio: auto 800 / 450;
}
Para imágenes adaptables (responsive), añade este CSS:
img {
height: auto;
max-width: 100%;
}
Los navegadores no necesitan descargar el archivo de imagen completo para calcular las dimensiones. El navegador conoce la relación y reserva el espacio vertical. El CSS hace la parte final: la contención. height: auto calcula el alto a partir de la relación. max-width: 100% evita que la imagen exceda su contenedor.
Cosas que deshacen la solución
Los atributos de ancho y alto son todo lo que necesitas para evitar que las imágenes causen cambios de diseño. Pero todavía hay algunos patrones comunes que deshacen el trabajo y hacen que las imágenes causen cambios de diseño incluso con dimensiones y CSS.
width:auto en CSS
Este es el que más veo y el que más tiempo de depuración hace perder. El desarrollador establece width y height en cada imagen, hace todo bien en el HTML pero en algún lugar del archivo CSS hay un width:auto extra para las imágenes.
img {
width: auto;
height: auto;
max-width: 100%;
}
El problema es width: auto. Debido a que la relación interna del navegador tiene la prioridad CSS más baja, cualquier regla la anula. width: auto elimina el ancho que el navegador estaba usando para calcular el alto. Ambas dimensiones se vuelven desconocidas. La imagen se renderiza a 0x0 hasta que el archivo se descarga y se conocen las dimensiones finales.
Establecer aspect-ratio en CSS no soluciona esto. Con width: auto, el navegador trata inicialmente el ancho como 0. Una relación de aspecto calculada a partir de 0 sigue produciendo 0x0.
Lo que hace que este sea difícil de atrapar es el almacenamiento en caché del navegador. Si la imagen está en la caché del navegador, las dimensiones reales están disponibles de inmediato y no ocurre ningún cambio. He depurado esto en docenas de sitios de clientes y siempre estaba en caché en la máquina del desarrollador.
La solución:
img {
height: auto;
max-width: 100%;
}
Elimina width: auto. Mantén height: auto y max-width: 100%. Este es el patrón recomendado por web.dev.
Comprobación rápida: haz clic derecho en cualquier imagen, inspecciónala, mira los estilos computados. Si ves width: auto, ese es tu problema. Para el tutorial completo, consulta cómo solucionar los cambios de diseño causados por imágenes con tamaño automático.
Dimensiones de imagen incorrectas
¿Recuerdas la relación de aspecto generada internamente? Aquí es donde las cosas se ponen un poco técnicas. La palabra clave auto le dice al navegador: usa esta relación como un marcador de posición, pero una vez que la imagen real se cargue, cambia a las dimensiones reales. Si estableces valores incorrectos (width="4" height="3" en una imagen 16:9), el navegador reserva inicialmente un espacio 4:3, luego corrige a 16:9 cuando la imagen se carga. Esa corrección es un cambio de diseño. Usa siempre las dimensiones en píxeles reales de la imagen.
Cuándo CSS aspect-ratio es la mejor opción
Los atributos de ancho/alto son el enfoque predeterminado y siempre el mejor enfoque, pero a veces tu CMS no te permitirá añadir dimensiones de imagen (¡y eso ocurre más de lo que crees!). En ese caso puedes controlar cuánto espacio se reserva usando la relación de aspecto de CSS. Por ejemplo, si tu imagen principal tiene la clase .hero puedes reservar su espacio así:
img.hero {
aspect-ratio: 16 / 9;
width: 100%;
}
Funciona en todos los navegadores modernos (Chrome 88+, Firefox 87+, Safari 15+) y en cualquier elemento, no solo imágenes y vídeos.
Vídeos, iframes y SVGs
Vídeos
Mismo problema, misma solución. Establece el ancho y el alto para que coincidan con la resolución del vídeo:
<video src="demo.mp4" width="1280" height="720" autoplay muted loop></video>
Añade height: auto; max-width: 100%; en CSS. Una cosa a tener en cuenta: establece las dimensiones para que coincidan con la resolución del vídeo, no con la imagen de póster. Si difieren, obtendrás un cambio cuando comience la reproducción.
Iframes
A diferencia de las imágenes, los iframes no calculan una relación de aspecto a partir de sus atributos. Sin dimensiones explícitas, por defecto son de 300x150 píxeles. Para la mayoría de las incrustaciones, eso es incorrecto. Para los iframes es mejor establecer la relación de aspecto (aspect-ratio) así:
.responsive-iframe {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
Mejor aún, no cargues el iframe en absoluto. Para YouTube, Vimeo, Google Maps e incrustaciones sociales dejé de cargar iframes en la carga de la página hace años. Muestra una imagen de marcador de posición estática con la relación de aspecto correcta. Cuando el iframe se vuelve visible, JavaScript lo intercambia con el iframe real. El cambio del intercambio ocurre dentro de los 500ms de la entrada del usuario y está excluido del CLS por diseño.
Para detalles de implementación, consulta incrustaciones de YouTube perfectas y Google Maps sin perder PageSpeed.
SVGs
Los SVGs cargados a través de <img> necesitan ancho y alto en la etiqueta, al igual que las imágenes rasterizadas. Los elementos <svg> en línea necesitan un viewBox con aspect-ratio de CSS. Sin ninguno de ellos, por defecto son 300x150.
Imágenes adaptables (Responsive images)
Mantén la misma relación en todas las fuentes de srcset
Todas las imágenes en un srcset deben compartir la misma relación de aspecto. Si lo hacen, un par de ancho/alto en el <img> es suficiente:
<img
src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 800px"
width="800" height="450"
alt="Imagen principal">
800:450 es la misma relación en las tres variantes. Sin importar cuál elija el navegador, el espacio reservado es correcto. Si necesitas diferentes relaciones, usa <picture> con elementos <source> en su lugar.
Dirección de arte: diferentes relaciones por punto de interrupción (breakpoint)
Cuando sirves diferentes recortes a diferentes anchos de ventana gráfica (viewport) necesitarás usar el elemento <picture>. Establece width y height en cada <source>:
<picture>
<source
media="(max-width: 799px)"
srcset="hero-mobile.jpg"
width="480" height="600">
<source
media="(min-width: 800px)"
srcset="hero-desktop.jpg"
width="1200" height="400">
<img
src="hero-desktop.jpg"
width="1200" height="400"
alt="Imagen principal de producto">
</picture>
Chrome y Safari recogen las dimensiones correctas de cualquier <source> que esté activo. Firefox no lo hace (error 1694741). Siempre usa las dimensiones del respaldo (fallback) <img>. Solución: haz coincidir los puntos de interrupción con consultas de medios (media queries) CSS.
picture img {
width: 100%;
height: auto;
}
@media (max-width: 799px) {
picture img {
aspect-ratio: 480 / 600;
}
}
@media (min-width: 800px) {
picture img {
aspect-ratio: 1200 / 400;
}
}
Si todos tus recortes comparten la misma relación, el error de Firefox no importa.
Contenedores fijos, carruseles y contención
object-fit para contenedores de tamaño fijo
Cuadrículas de tarjetas de producto donde cada tarjeta tiene la misma altura pero las imágenes tienen diferentes relaciones. Bloquea el contenedor, deja que la imagen lo llene:
.product-image {
width: 100%;
aspect-ratio: 1 / 1;
object-fit: cover;
object-position: center;
}
<img
src="product.jpg"
width="400" height="600"
class="product-image"
alt="Nombre de producto">
El tamaño se bloquea antes de que la imagen se cargue. Esto también reemplaza las imágenes de fondo de CSS. Las imágenes de fondo no pueden ser cargadas de forma diferida (lazy loaded), el escáner de precarga no las encuentra, y no puedes usar fetchpriority. Un <img> con object-fit: cover te da todos esos controles.
Carruseles
Las transiciones de diapositivas que animan left, width, o margin desencadenan un recalculo del diseño. Debido a que la reproducción automática (autoplay) no es entrada del usuario, cada cambio cuenta para CLS. Fija el contenedor con una relación de aspecto fija. Anima con transform: translateX() en su lugar. Las transformaciones se ejecutan en la GPU y nunca desencadenan el diseño.
Contención para incrustaciones que no puedes controlar
Espacios de anuncios, widgets de terceros, contenido generado por el usuario. No controlas lo que renderizan y no puedes recortarlos. El objetivo realista es minimizar el cambio, no eliminarlo.
Comienza reservando espacio:
.ad-slot {
min-height: 250px;
contain: layout style;
}
El min-height maneja la gran victoria. Si el anuncio se carga a 250px o menos, no hay cambio. Si se carga a 300px, obtienes un cambio de 50px en lugar de un cambio de 300px desde cero. Esa diferencia importa.
contain: layout hace algo diferente. No impide que el contenedor crezca. Aísla lo que sucede en el interior. Cuando la red publicitaria inyecta scripts que refluyen su propio contenido (redimensionando iframes, inyectando nuevos elementos, recalculando el diseño interno), esos recalculos se mantienen dentro del contenedor. Sin contención, cada reflujo interno en el anuncio desencadena un recalculo de diseño para toda la página. Con ella, el navegador omite todo lo que está fuera de la caja. Eso hace que la página sea más responsiva mientras los anuncios se están cargando.
contain: style evita que los contadores CSS y otros efectos secundarios de estilo se filtren. Un seguro barato.
Para el valor de min-height, comprueba los tamaños creativos más comunes de tu proveedor de anuncios y elige el que cubra la mayoría de las impresiones. Si el 90% de tus anuncios son de 250px y el 10% son de 300px, ajústalo a 250px y acepta el pequeño cambio ocasional. Ajustarlo a 300px significa que el 90% de las cargas de página tienen 50px de espacio vacío colapsando cuando se carga un anuncio más pequeño. Ese colapso también es un Cumulative Layout Shift.
No hay respuesta perfecta para los anuncios. El objetivo es el cambio más pequeño posible en la mayoría de las cargas de página.
Cómo encontrar el CLS de las imágenes
No atraparás el CLS de las imágenes bajo condiciones de navegación normales. La caché de tu navegador ya tiene las dimensiones de una visita anterior por lo que el cambio nunca ocurre. Para ver lo que tus usuarios reales ven, abre DevTools (F12), ve a la pestaña Red (Network) y marca "Deshabilitar caché" (Disable cache). La caché solo está deshabilitada mientras DevTools está abierto. Alternativamente, usa una ventana de incógnito.
Monitorización de usuarios reales (RUM)
Comienza con CoreDash u otra herramienta RUM. Los datos de atribución de CLS muestran exactamente qué elementos cambiaron. Navega a CLS, mira la tabla de atribución de Elementos. Filtra por imagen y obtendrás cada elemento de imagen afectado por cambios de diseño, ordenados por impacto.

Chrome DevTools
Deshabilita la caché en la pestaña Red, estrangula (throttle) a 4G Lento, habilita capturas de pantalla, recarga. Observa los saltos visuales. Luego abre el panel de Rendimiento (Performance) y busca las entradas "Layout Shift". Haz clic en un cambio para ver el nodo, la puntuación, y si tuvo entrada de usuario reciente.
Core Web Vitals Visualizer
La extensión Core Web Vitals Visualizer resalta cada Cumulative Layout Shift con una superposición coloreada. Uso esto como mi primer paso antes de abrir el panel de Rendimiento. Recarga con la extensión activa y verás exactamente lo que se movió.
Lista de verificación rápida para solucionar CLS
| Elemento | Causa de CLS | Solución |
|---|---|---|
<img> |
Ancho/alto (width/height) faltante | Añadir width y height; usar height: auto; max-width: 100%; en CSS |
<img> |
CSS width: auto anulando dimensiones |
Eliminar width: auto; mantener solo height: auto |
<img> |
Valores de ancho/alto incorrectos | Usar las dimensiones reales en píxeles de la imagen |
<video> |
Ancho/alto faltante | Añadir width y height coincidiendo con la resolución del vídeo |
<iframe> |
300x150 por defecto | CSS aspect-ratio: 16 / 9; width: 100%; o el patrón de fachada (facade pattern) |
<picture> |
Diferentes relaciones por fuente (Error de Firefox) | Establecer ancho/alto en cada <source>; añadir media query de CSS como respaldo |
<img srcset> |
Relaciones mixtas en srcset | Misma relación para todas las fuentes; establecer ancho/alto en el <img> |
| Carga diferida JS | Marcador de posición 1x1 con relación incorrecta | Usar loading="lazy" nativo o igualar la relación del marcador de posición |
| Carrusel | Autoplay + transiciones que desencadenan diseño | Contenedor con aspect-ratio fijo; transform para transiciones |
| SVG | Sin dimensiones incorporadas | Ancho/alto en <img> o viewBox + CSS aspect-ratio |
| Espacios de anuncios / incrustaciones | Dimensiones desconocidas | min-height + contain: layout style |
Dónde se encuentra la web respecto al CLS de imágenes
Los números del 2025 Web Almanac:
- El 62% de las páginas móviles tienen al menos una imagen sin tamaño. Menos que el 66% en 2024. Todavía la mayoría.
- El 65% de las páginas de escritorio tienen imágenes sin tamaño. Menos que el 69%.
- En el percentil 75 (p75), una página de escritorio tiene 9 imágenes sin tamaño. Las móviles tienen 8.
- Altura mediana de las imágenes sin tamaño: 111px en escritorio, 98px en móviles. Suficiente para desplazar un párrafo.
- El 72% de los orígenes de escritorio y el 81% de los móviles aprueban en CLS. Más que el 62% en 2021.
El CLS ha mejorado más que cualquier otro Core Web Vital durante los últimos cuatro años. Las imágenes sin tamaño siguen siendo el mayor contribuyente. Soluciona este único problema y los cambios de diseño desaparecen en la mayoría de los sitios.
Guías relacionadas
- Qué es el Cumulative Layout Shift (CLS): La guía completa. Fórmula, umbrales, ventanas de sesión y todas las causas del CLS más allá de las imágenes.
- Encontrar y solucionar problemas de CLS: Diagnósticos paso a paso con datos RUM, DevTools y soluciones para cada causa.
- Solucionar el cambio de diseño causado por imágenes con tamaño automático: El tutorial completo de
width: auto. - Optimizar imágenes para los Core Web Vitals: Precarga, imágenes adaptables, formatos, priorización.
- Cambio de diseño causado por transiciones CSS: Cómo las animaciones que desencadenan diseños causan CLS.
- Incrustaciones de YouTube perfectas: El patrón de fachada para un CLS cero.
- Google Maps 100% PageSpeed: El mismo enfoque de fachada para Maps.
CoreDash has MCP built in.
Connect it to Claude or any AI agent. Ask it why your INP spiked last Tuesday.
See how it worksPreguntas respondidas sobre el CLS en imágenes y medios
¿Por qué width:auto en las imágenes causa Cumulative Layout Shift incluso cuando se establecen los atributos width y height?
La relación de aspecto interna del navegador a partir de los atributos width/height tiene la prioridad CSS más baja. width: auto la anula, haciendo que ambas dimensiones sean desconocidas. La imagen se renderiza a 0x0 hasta que se descarga el archivo. Elimina width: auto y mantén solo height: auto; max-width: 100%;.
¿Necesito width y height en los elementos video y iframe también?
Sí para los vídeos. Mismo mecanismo. Los iframes son diferentes: no calculan una relación a partir de los atributos y por defecto son de 300x150. Usa el aspect-ratio de CSS o el patrón de fachada.
¿Cómo evito el CLS con el elemento picture cuando las relaciones de aspecto difieren según el punto de interrupción (breakpoint)?
Establece width y height en cada <source>. Chrome y Safari usan las dimensiones correctas. Firefox tiene un error donde siempre usa el respaldo <img>. Añade media queries CSS con el aspect-ratio correcto por punto de interrupción como solución alternativa.
¿La carga diferida (lazy loading) causa Cumulative Layout Shift?
No si la imagen tiene los atributos width y height. Pero la carga diferida de imágenes situadas en la mitad superior de la página (above-the-fold) retrasa el LCP sin ningún beneficio. Nunca uses loading="lazy" en imágenes que se encuentren en la ventana gráfica inicial.
¿Por qué Lighthouse muestra un buen CLS pero mis datos de campo muestran cambios de diseño?
Lighthouse se ejecuta en un navegador preparado con una red rápida. No detecta el problema de width: auto porque comprueba los atributos HTML, no los estilos CSS computados. Verifica siempre el CLS con datos de campo de CrUX o una herramienta RUM como CoreDash.

