Cómo corregir Layout shift culprits en Lighthouse y PageSpeed

Qué se movió mientras cargaba la página, cómo comprobar el elemento que señala Lighthouse y cómo corregir los shifts provocados por imágenes, fuentes, anuncios, barras y CSS tardío.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-11-05

¿Por qué aparece en rojo Layout shift culprits en PageSpeed Insights?

Layout shift culprits se pone en rojo cuando los layout shifts durante la carga suman un CLS de 0,1 o más: «Los layout shifts se producen cuando los elementos se mueven sin que haya interacción del usuario». Antes, Lighthouse lo llamaba Avoid large layout shifts. Muestra qué se ha movido e intuye la causa. Reserva espacio para lo que llega tarde: width y height en las imágenes, una altura en los slots de anuncios.

¿Solo quieres una solución rápida? Ve directo a imágenes, web fonts, anuncios y embeds o banners.

¿Cómo se lee la tabla de Layout shift culprits?

Lighthouse registra una sola carga de la página en una pantalla de tamaño móvil y agrupa los layout shifts en ráfagas (shifts que ocurren con menos de un segundo de diferencia), con una tabla por ráfaga. El aviso aparece en rojo cuando la peor ráfaga suma 0,1 o más, y en gris si queda por debajo. Apunta a 0 incluso si está en gris: un shift inferior a 0,1 sigue moviendo el texto que lee el visitante.

En una página de recetas que monté imitando un blog de cocina en WordPress —con una web font en el titular, un plugin de newsletter, un anuncio bajo la cabecera y un plugin de recetas—, el aviso salía en rojo con una ráfaga de 0,241.

Aviso de Layout shift culprits en Lighthouse en rojo en una página de recetas: Total de 0,241 y cuatro shifts. Los elementos desplazados son div.entry-content, main, el título de la ficha de receta y article. Bajo tres de ellos, la línea de causa indica Unsized image element apuntando a la imagen destacada, que tiene width 1200 y height 675; la fila de la fuente indica también Web font y la fila de la receta señala la foto del plato.

El aviso de la página de recetas en Lighthouse 13.5, móvil, con throttling simulado como en PageSpeed Insights.

  • Total es la puntuación de la ráfaga; el Total de la peor ráfaga es el CLS que reporta Lighthouse.
  • Element es lo que más se movió en ese shift, a menudo un contenedor grande como <main>. Lo que lo empujó suele estar situado encima.
  • Layout shift score es la parte del Total que corresponde a ese shift individual.
  • La línea debajo de cada fila es la causa estimada por Lighthouse: "Unsized image element" con la imagen, o "Web font" con el archivo de la fuente. Una fila puede tener ambas cosas o ninguna.

En la página de recetas, Lighthouse señaló la imagen equivocada en tres de los cuatro shifts: comprueba qué elemento se movió de verdad antes de cambiar nada.

¿Por qué da saltos la página mientras carga?

El visitante empieza a leer y el texto se mueve, o va a pulsar un enlace y toca lo que acaba de ocupar su lugar.

El navegador pinta la página con lo que tiene disponible. Todo lo que llega más tarde sin un espacio reservado empuja el contenido inferior: una imagen sin tamaño empieza con altura cero y una web font hace el titular más ancho de lo que ocupaba el fallback. Cada movimiento es un layout shift, puntuado según cuánta pantalla se mueve y a qué distancia. Los shifts que ocurren con menos de un segundo de diferencia forman una ráfaga, y el CLS es la puntuación de la peor ráfaga; por eso los pequeños shifts consecutivos se acumulan.

En la página de recetas, cada causa se queda por debajo de 0,1 por separado, y las cuatro ocurren en una sola ráfaga:

Causa en la página de recetasCLS por separadoTras el fix
Web font del titular0,0350
Foto de la receta sin width ni height0,0360
Barra de newsletter sobre la cabecera0,0580
Anuncio en un slot vacío0,0540
Las cuatro juntas0,2410

Las cuatro juntas puntúan más que la simple suma de las filas, porque en la página completa la fuente y la foto mueven una porción mayor de pantalla. Corregir las cuatro subió la puntuación de Performance en móvil de 87 a 100, sin alterar FCP, LCP ni Total Blocking Time. El CLS supone una cuarta parte de esa puntuación, pero Google posiciona la página según el CLS que experimentan los visitantes reales.

La página de recetas en un móvil en su primer pintado: cabecera, una etiqueta de anuncio vacía, el titular en dos líneas con la fuente de fallback, la línea de autor y la foto destacada.

Antes, primer pintado

La misma página dos segundos después: una barra verde de newsletter sobre la cabecera, un anuncio debajo, el titular en tres líneas con la web font y la foto más abajo del recuadro discontinuo que marca dónde estaba en el primer pintado.

Antes, a los 2 segundos

La página corregida en su primer pintado: una franja vacía donde irá la barra, un slot de anuncio vacío a su altura completa y el titular ya en tres líneas con la fuente de fallback ajustada.

Después, primer pintado

La página corregida dos segundos después: la barra y el anuncio han ocupado su espacio, el titular se muestra con la web font y la foto sigue donde estaba en el primer pintado.

Después, a los 2 segundos

La página de recetas con el tamaño de móvil de Lighthouse. El recuadro discontinuo marca dónde estaba la foto en el primer pintado.

¿Señaló Lighthouse al elemento correcto?

Lighthouse deduce la causa según los tiempos: una web font que terminó de descargarse justo antes del shift, una imagen que el navegador pintó justo después. Así, una imagen que solo fue empujada puede figurar como "Unsized image element". La imagen destacada de la página de recetas tiene width="1200" height="675"; aun así, Lighthouse la señala en los shifts de la fuente, de la barra de newsletter y del anuncio. Si una fila no tiene ninguna línea debajo, empieza en el paso 2.

  1. ¿Tiene dimensiones la imagen señalada? "Image elements do not have explicit width and height", bajo Diagnostics en el mismo informe, lista las imágenes a las que les falta. En DevTools, la pestaña Computed de la imagen muestra una proporción en aspect-ratio (auto 1200 / 675) cuando su espacio está reservado, y solo auto cuando no lo está. Una imagen con tamaño definido no causó el shift, salvo que el tema aplique width: auto (Unsized image element más abajo): mira la otra línea bajo la fila, con frecuencia "Web font", o pasa al paso 2.
  2. ¿Qué apareció en ese instante? Graba una recarga en el panel Performance. Cada shift es un rombo morado en la pista Layout shifts; pasa el cursor por encima para ver su puntuación y una captura del momento con la zona desplazada resaltada. En la página de recetas, el shift de 0,0583 muestra la barra verde de newsletter que acababa de asomar arriba. Para shifts al hacer scroll: pulsa Record, haz scroll y pulsa Stop.
  3. Bloquea el recurso sospechoso y recarga. En el panel Network, haz clic derecho en la petición sospechosa —como el archivo de la fuente o el script del anuncio—, elige Block requests, luego Block request URL y vuelve a grabar. Si un rombo desaparece, pertenecía a esa petición: bloquear la fuente de la página de recetas eliminó un shift y dejó los otros tres. Desmarca el bloqueo en el panel Request conditions al terminar.
Panel Performance de Chrome DevTools: la pista Layout shifts con cuatro rombos en el peor clúster de layout shifts, el tooltip del shift de 0,0583 mostrando la página con la barra verde de newsletter que acaba de aparecer sobre la cabecera, y el insight Layout shift culprits a la izquierda listando dos imágenes sin tamaño y una web font.

Paso 2 en la página de recetas: Chrome 155, Slow 4G y ralentización de CPU 4×.

Sin DevTools, cRUM en CoreDash hace esta comprobación: coloca una traza de Chrome de la página junto a lo que experimentaron los visitantes reales, indica qué elemento se movió y muestra qué hizo el visitante justo antes. La captura de abajo corresponde a otra página: empieza por Chrome trace y Real users.

CoreDash cRUM para una página en móvil: Chrome trace arriba y, bajo Real users, los paneles When it shifts, What shifts y What preceded it.

CoreDash cRUM para una página en acme-pagespeed.com, móvil.

¿Qué elementos se mueven con los visitantes reales?

Lighthouse carga la página una sola vez, como un visitante nuevo, y nunca hace scroll ni toca la pantalla. Los field data recogen todas las visitas reales: el anuncio a mitad de artículo que carga cuando el usuario baja con el scroll, o la cabecera que encoge al desplazarse. Cuando Lighthouse aparece limpio o en gris y Search Console dice que el CLS es deficiente, los shifts casi siempre ocurren después de la carga.

En CoreDash, selecciona el dispositivo móvil y agrupa el CLS por Attribution Element (CLS) para ver qué elementos se movieron; Last interaction (CLS), dentro de More dimensions, te indica si ocurrió tras hacer scroll. Para averiguar qué empujó a esos elementos, graba la página en el panel Performance mientras haces scroll (paso 2 de la comprobación anterior).

CoreDash, Cumulative Layout Shift por Attribution Element (CLS) en móvil: por elemento el p75 de CLS, una etiqueta de rendimiento, la distribución y las sesiones; las filas incluyen main#main.site-main, el nombre de la receta, un slot de anuncio integrado en el contenido, el nav y el footer.

CoreDash en móvil, p75: empieza por el CLS más alto.

¿Cómo corregir Layout shift culprits?

Empieza por el shift más grande de la tabla con el Total más alto, una vez que la comprobación anterior haya confirmado la causa.

Unsized image element

Una imagen sin tamaño empieza con altura cero y empuja hacia abajo todo lo que tiene debajo al cargar. WordPress añade width y height a las imágenes de la biblioteca de medios; pero las que genera directamente un tema, page builder, slider o plugin suelen carecer de ellos, como la foto de la ficha de receta. Si no puedes modificar el tema, WP Rocket añade las medidas que faltan (Media, Add missing image dimensions); en una plantilla, añádelas tú mismo:

<img src="shakshuka.jpg" width="800" height="600" alt="Shakshuka in the pan">
img { max-width: 100%; height: auto; }

El navegador convierte ambos atributos en una proporción y reserva la altura correcta en cualquier ancho de pantalla antes de que llegue el archivo. Un width: auto en el CSS del tema anula esa proporción (imágenes con auto sizing). En Shopify, el filtro image_tag añade las dimensiones; un tema o app que genere su propio <img> necesita width="{{ image.width }}" height="{{ image.height }}". En Next.js, next/image requiere width y height, o bien fill dentro de un contenedor padre con tamaño propio.

Web font

El titular aparece primero con la fuente de fallback y luego con la web font, que es más ancha o más estrecha: las líneas parten en palabras distintas y todo lo que está debajo se mueve. En WordPress (CSS adicional) y en Shopify (la hoja de estilos del tema en Edit code; una actualización del tema puede sobrescribirlo), se añade una regla @font-face de fallback que escala una fuente local a las dimensiones de la web font. En Next.js, next/font genera un fallback a medida. Esta es la tipografía del titular en la página de recetas:

@font-face {
  font-family: "Young Serif Fallback";
  src: local("Times New Roman"), local("Liberation Serif");
  size-adjust: 131%;
  ascent-override: 79.85%;
  descent-override: 27.94%;
  line-gap-override: 0%;
}
h1 { font-family: "Young Serif", "Young Serif Fallback", serif; }

Un size-adjust del 122% calculado con una herramienta aún dejaba un CLS de 0,029; al 131% dio 0. En Font display tienes la regla para Android, cómo obtener tus propios valores y la opción font-display: optional, que elimina el shift mostrando el fallback a quienes visitan la página por primera vez.

Anuncios, vídeos y otros embeds

El script de publicidad inserta su iframe en el slot tras la subasta; si el slot estaba vacío, todo el contenido inferior cae de golpe la altura del anuncio. Según el State of Web Vitals, el 89% de las webs sin redes publicitarias aprueban el CLS en móviles, frente al 73% de los sitios con dos o más redes. Es una correlación.

En el tema o en el plugin de anuncios, asigna al contenedor del anuncio la altura del formato más habitual y define el iframe como bloque:

.ad-slot { min-height: 50px; }
.ad-slot iframe { display: block; }

Por defecto, un iframe se alinea con la línea de texto, por lo que el slot reservado en la página de recetas seguía creciendo 8 píxeles hasta convertir el iframe en bloque. Mantén el slot abierto cuando no haya anuncio: cerrarlo mueve la página tanto como rellenarlo. Los anuncios automáticos de AdSense se colocan donde Google decide: excluye las zonas de la primera pantalla (Ad settings, Excluded areas) y coloca ahí una unidad manual en un slot con tamaño reservado.

YouTube, los mapas y otros embeds también son iframes, y en un iframe los atributos width y height no generan una relación de aspecto: con height: auto se encoge a unos 150 píxeles. Dale al iframe un aspect-ratio o usa una facade: una miniatura con dimensiones que se convierte en el iframe al hacer clic (YouTube, Google Maps):

.video-embed iframe { width: 100%; height: auto; aspect-ratio: 16 / 9; }

Barras y banners insertados por script

Una barra de newsletter o una franja de envío gratis que un script coloca sobre la cabecera empuja toda la página hacia abajo.

Empieza por la configuración de diseño del plugin o de la app: una barra inferior, una caja flotante o un popup flotan sobre la página y no mueven nada. Las herramientas de consentimiento como OneTrust y CookieYes ofrecen esos mismos formatos; Lighthouse ve su banner en cada análisis porque arranca sin cookies. Si la barra tiene que ir sí o sí sobre la cabecera, resérvale espacio en el tema a la altura que marque la pestaña Computed en ancho móvil:

<div id="promo-slot" style="min-height: 48px"></div>

Si la barra solo se muestra en algunas visitas, haz que flote o renderízala en el HTML desde el servidor. El contenido visible inyectado mediante una etiqueta de Google Tag Manager siempre llega después del primer pintado: pásalo a la plantilla. En Shopify, cualquier app que inyecte un widget —como estrellas de reseñas o una barra de avisos— necesita una altura en el contenedor donde se inserta su app block.

CSS que carga tras el primer pintado

Una hoja de estilos cargada con el truco de media="print", o pospuesta o cargada de forma asíncrona por un plugin de optimización, llega cuando la página ya está en pantalla y redimensiona lo que ya hay: si la cabecera crece, empuja todo lo que tiene debajo. En el plugin, exclúyela de la opción que retrasa el CSS o lo carga de forma asíncrona; en el tema, cárgala con un <link rel="stylesheet"> estándar en el head.

Animaciones, sliders y bloques renderizados por JavaScript

Suelen provenir del tema, de un plugin o de una app: busca si tienen algún ajuste para ello. Si no lo hay, pásale a un desarrollador el elemento que indica el informe y el código siguiente.

Una animación de top, left, height o margin recalcula el layout en cada fotograma. Lighthouse la muestra como varias filas pequeñas sin línea de causa, y la auditoría "Avoid non-composited animations" en Diagnostics señala el elemento. Anima transform en su lugar: mueve los píxeles del elemento sin alterar nada a su alrededor, por lo que el navegador no registra ningún layout shift.

.promo { position: fixed; top: 0; left: 0; right: 0;
         transform: translateY(-100%); transition: transform .3s; }
.promo.is-open { transform: translateY(0); }

Un slider muestra las diapositivas apiladas hasta que su script se ejecuta; mantenlo mostrando solo la primera diapositiva hasta que el script añada la clase de preparado (usa la que corresponda a tu slider):

.slider:not(.is-ready) > :not(:first-child) { display: none; }

Un bloque que JavaScript renderiza tras la carga —como reseñas o productos relacionados— necesita un contenedor vacío con su altura final, o bien renderizarse directamente en el servidor. Para animaciones activadas al hacer scroll, consulta animaciones al hacer scroll y transiciones CSS.

Shifts provocados por código que no puedes editar

No puedes modificar lo que inserta una creatividad publicitaria, una app sin opciones de diseño o el script de un proveedor externo. Reserva la altura que suele ocupar, colócalo por debajo de la primera pantalla o sustitúyelo por una alternativa que respete su espacio.

¿Consiguieron los cambios bajar el CLS a 0?

Comprueba el fix en Lighthouse en móvil, tras purgar la CDN y el plugin de caché. Si han desaparecido todos los shifts, Layout shift culprits saldrá como aprobado y el CLS será 0. Una grabación en el panel Performance —una con recarga y otra haciendo scroll— mostrará vacía la pista Layout shifts. CoreDash reflejará el nuevo CLS por elemento a partir de las siguientes visitas; Search Console tarda hasta 28 días.

Lighthouse con ancho móvil en la página de recetas antes de los fixes: puntuación 87, CLS 0,241 en naranja, el resto de métricas en verde y Layout shift culprits en rojo.

Antes

Lighthouse con ancho móvil en la misma página tras los fixes: puntuación 100, CLS 0 y Layout shift culprits en la sección de insights superados.

Después

Antes y después de los cuatro fixes: Lighthouse 13.5, móvil, throttling simulado.

Hay shifts que proceden de sitios a los que no tienes acceso: un slot de anuncios que gestiona tu socio publicitario, una app que inyecta su widget o un shift que solo los visitantes reales provocan al hacer scroll. En una power hour de Core Web Vitals revisamos los field data y una grabación de la página para decidir qué altura asignar a cada contenedor.

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.

 
Arjen Karel

¿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
Arjen Karel
Arjen Karel, Consultor de rendimiento web desde 2009

¿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.

Cómo corregir Layout shift culprits en Lighthouse y PageSpeed Core Web Vitals Cómo corregir Layout shift culprits en Lighthouse y PageSpeed