Cómo las imágenes y los medios causan Layout Shift (y cómo solucionarlo)

La guía completa para prevenir CLS por imágenes, videos, iframes, imágenes responsivas e incrustaciones de medios

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-03-27

Cómo las imágenes y los medios causan Layout Shift (y cómo solucionarlo)

El 2025 Web Almanac le pone un número a lo que sigo viendo en el campo: el 62% de las páginas móviles tienen al menos una imagen sin width y height 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 shifts es evitable con técnicas que han existido desde 2019.

Última revisión por Arjen Karel en marzo de 2026

El navegador no sabe qué tamaño tiene su imagen

Cada layout shift de una imagen se reduce a una sola cosa. El navegador no sabe cuánto espacio reservar antes de que la imagen cargue.

Cuando el navegador encuentra una etiqueta <img> sin dimensiones, renderiza la imagen a 0x0 píxeles. El archivo llega, el navegador recalcula el layout, y todo lo que está debajo de la imagen salta hacia abajo. Ese salto es su CLS.

Cómo width y height previenen el layout shift

En 2019 y 2020 todos los principales navegadores lanzaron una característica que cambió cómo funcionan los atributos width y height. Los navegadores ahora los usan para calcular un aspect ratio antes de que la imagen se descargue.

Cuando escribe esto:

<img src="hero.jpg" width="800" height="450" alt="Description">

El navegador genera internamente esto:

img[Attributes Style] {
    aspect-ratio: auto 800 / 450;
}

No se necesitan datos de la imagen. El navegador conoce la proporción y reserva el espacio vertical.

Esta proporción interna tiene la prioridad CSS más baja, por lo que cualquier regla CSS que escriba la sobrescribe. Eso importa porque es la razón por la que width: auto rompe todo (más sobre esto en un momento).

La palabra clave auto le dice al navegador: use esta proporción como un placeholder, pero una vez que la imagen real cargue, cambie a las dimensiones reales. Si accidentalmente establece valores incorrectos (digamos width="4" height="3" en una imagen 16:9), el navegador reserva el espacio 4:3 inicialmente, luego corrige a 16:9 cuando la imagen carga. Esa corrección es un layout shift. Use siempre las dimensiones reales en píxeles.

Para imágenes responsivas, agregue este CSS:

<style>
img {
    height: auto;
    max-width: 100%;
}
</style>

height: auto calcula la altura a partir de la proporción. max-width: 100% evita que la imagen exceda su contenedor. El navegador conoce el width y la proporción. Eso es suficiente.

Por qué width:auto rompe su CLS

Esta es la que más veo y la que más tiempo de depuración desperdicia. El desarrollador establece width y height en cada imagen, hace todo bien en el HTML, ejecuta Lighthouse, obtiene una puntuación verde, lo publica. Luego llegan las quejas de CLS de los usuarios reales.

La causa siempre está en alguna parte del CSS. Una regla global deshace todo:

<style>
img {
    width: auto;
    height: auto;
    max-width: 100%;
}
</style>

El problema es width: auto. Debido a que la proporción interna del navegador tiene la prioridad CSS más baja, cualquier regla la sobrescribe. width: auto elimina el width que el navegador estaba usando para calcular el height. Ambas dimensiones se vuelven desconocidas. La imagen se renderiza a 0x0 hasta que el archivo se descarga, luego salta a su tamaño completo.

Establecer aspect-ratio en CSS no soluciona esto. Con width: auto, el navegador trata el width como 0 antes de que la imagen cargue. Un aspect ratio calculado desde 0 aún produce 0. Cero multiplicado por cualquier cosa es cero.

Aquí está la parte que hace que esto sea tan difícil de detectar: solo causa un shift para los visitantes por primera vez. Si la imagen está en la caché del navegador, las dimensiones reales están disponibles de inmediato y no ocurre ningún shift. Usted, como desarrollador, nunca lo verá en su propia máquina. Sus testers no lo verán. Su equipo de QA no lo verá. Solo sus usuarios reales en su primera visita lo ven, que es exactamente la visita que Google mide para CrUX.

He pasado horas en llamadas con equipos de ingeniería que juraban que su CLS estaba arreglado porque no podían reproducirlo localmente. Siempre era esto. Revise su CSS. Si tiene un width: auto global en las imágenes, ese es su problema.

La solución:

<style>
img {
    height: auto;
    max-width: 100%;
}
</style>

Elimine width: auto. Mantenga height: auto y max-width: 100%. Este es el patrón recomendado por web.dev.

Revisión rápida: haga clic derecho en cualquier imagen de su sitio, elija "Inspeccionar elemento", y mire los estilos calculados. Si ve width: auto, ahora sabe qué hacer. Para la guía completa, consulte cómo solucionar el layout shift causado por imágenes con tamaño automático.

Cuándo CSS aspect-ratio es la mejor opción

Los atributos width/height son el enfoque predeterminado. Pero a veces desea que CSS fuerce una proporción específica independientemente del contenido de la imagen. Un banner hero que siempre debe ser 16:9, o una cuadrícula de tarjetas de productos donde cada imagen necesita la misma forma:

<style>
img {
    aspect-ratio: 16 / 9;
    width: 100%;
}
</style>

Funciona en todos los navegadores modernos (Chrome 88+, Firefox 87+, Safari 15+) y en cualquier elemento, no solo en imágenes y videos.

Para imágenes de contenido regular, los atributos width/height son mejores. Describen las dimensiones reales y se autocorrigen cuando la imagen carga.

Puede combinar ambos:

<style>
img {
    aspect-ratio: auto 16 / 9;
    width: 100%;
}
</style>

La palabra clave auto aquí significa: use 16/9 antes de que la imagen cargue, cambie a la proporción natural después. Reserva de espacio antes de la carga, tamaño preciso después.

Los videos tienen el mismo problema

Un video sin width y height se renderiza a 0x0 hasta que el navegador descarga lo suficiente del archivo para leer sus metadatos. En una conexión lenta, eso toma segundos. La solución es idéntica a la de las imágenes:

<video src="demo.mp4" width="1280" height="720" autoplay muted loop></video>

Los navegadores calculan un aspect-ratio: auto 1280 / 720 interno a partir de los atributos. Agregue height: auto; max-width: 100%; en el CSS y listo.

Una cosa a tener en cuenta: la imagen poster. Si establece un poster pero no establece las dimensiones en el elemento de video, el elemento ajusta su tamaño al poster. Cuando el video comienza a reproducirse y tiene una resolución diferente, obtiene un shift. Establezca el width y el height para que coincidan con la resolución del video, no con la del poster.

Los iframes por defecto son de 300x150 píxeles

Un iframe sin dimensiones explícitas tiene por defecto 300x150 píxeles. Para la mayoría de las incrustaciones (YouTube, Google Maps, publicaciones de redes sociales) eso es incorrecto. En el momento en que la incrustación carga y cambia de tamaño, todo a su alrededor sufre un shift.

A diferencia de las imágenes, los iframes no calculan automáticamente un aspect ratio a partir de sus atributos. Tiene que configurar el tamaño usted mismo:

<style>
.responsive-iframe {
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
}
</style>

Esto reemplaza el viejo truco del padding-top donde envolvía el iframe en un contenedor con padding-top: 56.25% y lo posicionaba de forma absoluta. El viejo truco todavía funciona. aspect-ratio es más limpio y no necesita contenedor.

O no cargue el iframe en absoluto

Para incrustaciones de YouTube, Vimeo, Google Maps y redes sociales dejé de cargar iframes en la carga de la página hace años. El patrón facade es mejor en todos los sentidos: muestre una imagen estática de placeholder con el aspect ratio correcto. Cuando el usuario hace clic, JavaScript la intercambia con el iframe real. Cero iframes, cero CLS, cero recursos desperdiciados.

El shift del intercambio ocurre dentro de los 500ms de la entrada del usuario y está excluido de CLS por diseño.

Para ejemplos de implementación, consulte incrustaciones perfectas de YouTube y Google Maps sin perder PageSpeed.

Dirección de arte: cuando los recortes móviles y de escritorio tienen diferentes proporciones

La dirección de arte es cuando sirve diferentes recortes en diferentes anchos del viewport. Un paisaje amplio en el escritorio, un retrato más ajustado en el móvil. El elemento <picture> maneja esto con elementos <source>.

El problema de CLS: estos recortes generalmente tienen diferentes aspect ratios. El navegador necesita saber qué dimensiones van con qué breakpoint. Puede establecer 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="Product hero image">
</picture>

Chrome y Safari recogen el width/height correcto de cualquiera de los <source> que esté activo. Firefox no. Hay un bug (bug 1694741) donde Firefox siempre usa las dimensiones del fallback de <img>, independientemente del source seleccionado. Si el recorte móvil tiene una proporción diferente, Firefox muestra un shift.

Si todos sus recortes comparten la misma proporción (solo diferentes resoluciones), este bug no importa. Solo se activa cuando las proporciones difieren entre breakpoints.

Solución alternativa para Firefox

Hasta que se publique la solución, use CSS media queries que coincidan con los breakpoints en sus elementos <source>:

<style>
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;
    }
}
</style>

Esto sobrescribe la proporción interna del navegador con CSS explícito por breakpoint. Funciona en todos los navegadores.

Mantenga la misma proporción en todos los sources de srcset

Las imágenes responsivas con srcset y sizes pueden causar CLS si los atributos width/height no coinciden con el source seleccionado. La regla es simple: todas las imágenes en un srcset deben compartir el mismo aspect ratio. Si lo hacen, un conjunto de width/height 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="Hero image">

800:450 es la misma proporción en las tres variantes. Sin importar cuál elija el navegador, el espacio reservado es correcto.

Si mezcla proporciones en el mismo srcset (un source a 16:9, otro a 4:3), el espacio reservado será incorrecto para al menos uno de ellos. No haga esto. Use <picture> con elementos <source> en su lugar si necesita diferentes proporciones.

Cuando sizes es incorrecto

El atributo sizes le dice al navegador qué tan ancha se renderizará la imagen en cada tamaño del viewport. Si no coincide con el layout CSS real, el navegador elige un source que es demasiado grande o demasiado pequeño. Esto no causa CLS (la proporción se mantiene igual), pero desperdicia ancho de banda o produce una imagen borrosa.

sizes=auto para imágenes con lazy loading

Chrome 126+ y Edge 126+ soportan sizes="auto" en imágenes con lazy loading. El navegador calcula el tamaño correcto del layout CSS en lugar de depender del atributo sizes escrito manualmente. No funciona en imágenes con eager loading porque el navegador necesita el tamaño del layout antes de que se haya analizado el CSS.

No utilice lazy loading para contenido above the fold

Hacer lazy loading a las imágenes above the fold causa dos problemas a la vez. Retrasa el LCP porque loading="lazy" oculta el recurso del escáner de precarga. El navegador no puede descubrir la imagen hasta después del layout. Y si la imagen también carece de dimensiones, obtiene un layout shift además del retraso en la carga.

El 2025 Web Almanac informa que el 16% de las páginas todavía aplican lazy loading a su imagen LCP. Eso es el 16% de la web retrasando su imagen más importante para un beneficio nulo.

loading="lazy" pertenece a las imágenes fuera del viewport inicial. En ningún otro lugar.

Los placeholders de 1x1 píxeles causan shifts masivos

Los scripts JavaScript de lazy loading a menudo usan un pequeño GIF transparente de 1x1 píxeles como placeholder en src mientras la URL real se encuentra en data-src. Cuando IntersectionObserver se activa, JavaScript los intercambia.

Esto causa CLS porque el placeholder de 1x1 se renderiza a 1px de altura. Cuando la imagen de 800x450 carga, el elemento salta de 1px a 450px. Si todavía está utilizando una librería JavaScript de lazy loading en 2026, deténgase. El loading="lazy" nativo maneja el placeholder internamente y respeta los atributos width/height. Ha tenido soporte completo en los navegadores desde 2022.

Si tiene una razón específica para mantener el lazy loading con JavaScript (umbrales de intersección, animaciones de fade-in), use un placeholder con el mismo aspect ratio que la imagen final. Un SVG transparente de 16x9 en lugar de 1x1.

LQIP hecho correctamente

Un placeholder de miniatura borrosa se ve mejor que un espacio vacío. La clave: preservar el aspect ratio. Si su imagen final es 800x450, su LQIP debería ser una versión pequeña (10x6 o 20x11) con la misma proporción. Escale la imagen con CSS, aplique un filtro de blur. Cuando la imagen real carga, reemplaza el blur con las mismas dimensiones. Sin shift.

Next.js hace esto automáticamente. El componente Image genera el width, height y blurDataURL en el momento del build. Cero CLS.

Use object-fit para contenedores de tamaño fijo

Cuadrículas de tarjetas de productos donde cada tarjeta tiene la misma altura pero las imágenes tienen diferentes proporciones. Veo este patrón constantemente:

<style>
.product-image {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    object-position: center;
}
</style>
<img
    src="product.jpg"
    width="400" height="600"
    class="product-image"
    alt="Product name">

aspect-ratio: 1 / 1 fuerza un cuadrado. object-fit: cover llena el cuadrado y recorta el desbordamiento. El tamaño está bloqueado antes de que la imagen cargue.

Así es también cómo se reemplazan las imágenes de fondo CSS con elementos <img> adecuados. Las imágenes de fondo no pueden usar lazy loading, no pueden usar fetchpriority, y el escáner de precarga no las encuentra hasta que el archivo CSS sea analizado. Un <img> con object-fit: cover le da todos los controles de rendimiento de los que carece una imagen de fondo.

Los carruseles de reproducción automática producen CLS infinito

Las transiciones de diapositivas que animan left, width o margin desencadenan el recálculo del layout. Debido a que el autoplay no es una entrada del usuario, cada shift cuenta para el CLS. Un carrusel de reproducción automática con transiciones que desencadenan el layout puede producir CLS de forma indefinida.

Fije las dimensiones del contenedor con un aspect ratio fijo, anime con transform: translateX() en lugar de left o margin-left (los transforms se ejecutan en la GPU y nunca desencadenan el layout), y si debe usar autoplay, las dimensiones del contenedor de la diapositiva no pueden cambiar. Cualquier cambio de tamaño cuenta como CLS.

En un carrusel sin autoplay, la mayoría de las transiciones ocurren dentro de los 500ms de un clic del usuario y están excluidas del CLS. El autoplay elimina esa protección. La guía de carruseles de web.dev cubre los detalles de implementación.

SVG, containment y otros casos atípicos

Los SVGs cargados a través de <img> necesitan width y height en la etiqueta, igual que las imágenes rasterizadas. Los elementos <svg> en línea necesitan dimensiones explícitas o un viewBox con CSS aspect-ratio. Un SVG sin ninguno de los dos usa por defecto 300x150.

Para incrustaciones que no puede controlar (espacios publicitarios, widgets de terceros, contenido generado por el usuario), use CSS containment para evitar que el shift se propague:

<style>
.embed-container {
    min-height: 250px;
    contain: layout style;
}
</style>

contain: layout style le dice al navegador que nada dentro de este contenedor afecta el layout fuera de él. La incrustación puede sufrir shifts, crecer o encogerse. El resto de la página se mantiene en su lugar.

Para secciones below the fold con medios pesados, content-visibility: auto con contain-intrinsic-size omite el layout para el contenido fuera de la pantalla. Sin contain-intrinsic-size, el elemento tiene cero altura y la expansión cuando el usuario hace scroll hacia él es un layout shift:

<style>
.below-fold-gallery {
    content-visibility: auto;
    contain-intrinsic-size: auto 500px;
}
</style>

La palabra clave auto significa: comience con 500px como una estimación, pero una vez que el navegador lo renderice y conozca la altura real, recuerde ese valor.

Cómo encontrar el CLS de las imágenes

No atrapará el CLS de las imágenes en su propia máquina. La caché de su navegador ya tiene las dimensiones. Necesita condiciones de un visitante por primera vez o datos de usuarios reales.

Real User Monitoring

Comience con CoreDash u otra herramienta RUM. Los datos de atribución de CLS muestran exactamente qué elementos sufrieron shifts. Simplemente navegue a CLS y mire la tabla Element de atribución. Le dirá exactamente qué elementos sufrieron shifts. Para encontrar imágenes, simplemente filtre por imagen y obtendrá una tabla de todos los elementos de imagen afectados por layout shifts ordenados por impacto.

Chrome DevTools

Desactive la caché en la pestaña Network, limite la velocidad a Slow 4G, habilite las capturas de pantalla, recargue. Esté atento a saltos visuales. Luego abra el panel Performance y busque las entradas "Layout Shift". Haga clic en un shift para ver el nodo, la puntuación y si tuvo alguna entrada reciente del usuario.

Core Web Vitals Visualizer

La extensión Core Web Vitals Visualizer resalta cada layout shift con una superposición de color. Uso esto como mi primer paso antes de abrir el panel Performance. Recargue con la extensión activa y verá exactamente qué se movió.

Lighthouse atrapa parte de ello

Lighthouse marca las imágenes sin width y height. Pero pasa por alto el problema de width: auto por completo porque los atributos HTML están presentes. CSS los está sobrescribiendo, y Lighthouse no comprueba los estilos calculados. Esta es la razón por la que nunca confío en una puntuación CLS verde de Lighthouse sin verificar también los datos de campo.

Lista de verificación de soluciones rápidas

Elemento Causa del CLS Solución
<img> Falta width/height Agregue width y height; use height: auto; max-width: 100%; en CSS
<img> CSS width: auto sobrescribiendo dimensiones Elimine width: auto; mantenga solo height: auto
<video> Falta width/height Agregue width y height que coincidan con la resolución del video
<iframe> Por defecto 300x150 CSS aspect-ratio: 16 / 9; width: 100%; o el patrón facade
<picture> Diferentes proporciones por source (bug de Firefox) Establezca width/height en cada <source>; agregue un fallback con media queries en CSS
<img srcset> Proporciones mezcladas en srcset Misma proporción para todos los sources; establezca width/height en el <img>
Imágenes con lazy loading Above the fold sin dimensiones Elimine loading="lazy"; establezca siempre las dimensiones
Lazy loading con JS Placeholder de 1x1 con proporción incorrecta Use el loading="lazy" nativo o iguale la proporción del placeholder
Carrusel Autoplay + transiciones que desencadenan el layout Contenedor de aspect-ratio fijo; transform para las transiciones
SVG Sin dimensiones integradas Width/height en <img> o viewBox + aspect-ratio en CSS
Espacios publicitarios / incrustaciones Dimensiones desconocidas min-height + contain: layout style

Dónde se encuentra la web en cuanto a 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. Sigue siendo la mayoría.
  • El 65% de las páginas de escritorio tienen imágenes sin tamaño. Menos que el 69%.
  • En el p75, una página de escritorio tiene 9 imágenes sin tamaño. El móvil tiene 8.
  • En el p90: 25 en escritorio, 22 en móvil.
  • Mediana de altura de imagen sin tamaño: 111px en escritorio, 98px en móvil. Suficiente para causar un shift en un párrafo.
  • El 72% de los orígenes de escritorio y el 81% de los móviles aprueban CLS. Más que el 62% en 2021.
  • El 40% de las páginas móviles todavía usan animaciones no compuestas que causan CLS por sí solas.

CLS ha mejorado más que cualquier otro Core Web Vital en los últimos cuatro años. Las imágenes sin tamaño siguen siendo el mayor contribuyente. Solucione este único problema y los layout shifts desaparecerán en la mayoría de los sitios.

Guías relacionadas

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.


CoreDash has MCP built in.

Connect it to Claude or any AI agent. Ask it why your INP spiked last Tuesday.

See how it works

Preguntas respondidas sobre el CLS de imágenes y medios

¿Por qué width:auto en imágenes causa layout shift incluso cuando los atributos width y height están configurados?

El aspect ratio interno del navegador (calculado a partir de los atributos width/height) tiene la prioridad CSS más baja. width: auto lo sobrescribe, haciendo que ambas dimensiones sean desconocidas. La imagen se renderiza a 0x0 hasta que el archivo se descarga. Elimine width: auto y mantenga solo height: auto; max-width: 100%;.

¿También necesito width y height en los elementos video e iframe?

Sí para el video. El mismo mecanismo de width/height funciona. Establezca los atributos para que coincidan con la resolución del video, no con la imagen poster. Los iframes son diferentes: no calculan una proporción a partir de los atributos y por defecto usan 300x150. Use aspect-ratio en CSS o el patrón facade.

¿Cómo prevengo el CLS cuando uso el elemento picture con diferentes aspect ratios por breakpoint?

Establezca width y height en cada <source>. Chrome y Safari usan las dimensiones correctas desde el source activo. Firefox tiene un bug (1694741) en el que siempre usa el fallback de <img>. Agregue media queries en CSS con el aspect-ratio correcto por breakpoint como solución alternativa.

¿El lazy loading causa layout shift?

No si la imagen tiene los atributos width y height. Pero aplicar lazy loading a imágenes above the fold retrasa el LCP sin ningún beneficio. Nunca use loading="lazy" en imágenes dentro del viewport inicial.

¿Por qué Lighthouse muestra un buen CLS pero mis datos de campo muestran layout shifts?

Lighthouse se ejecuta en un navegador cálido con una red rápida. No detecta el problema de width: auto porque comprueba los atributos HTML, no los estilos CSS calculados. Tampoco prueba los shifts posteriores a la carga provocados por anuncios, incrustaciones o contenido con lazy loading. Verifique siempre el CLS con datos de campo de CrUX o una herramienta RUM como CoreDash.

Cómo las imágenes y los medios causan Layout Shift (y cómo solucionarlo)Core Web Vitals Cómo las imágenes y los medios causan Layout Shift (y cómo solucionarlo)