Lazy loading: guía de carga diferida
Carga solo lo que el usuario necesita ver para mejorar rendimiento, consumo de datos y experiencia
Lazy loading (carga diferida) es una técnica de optimización que retrasa la carga de recursos no visibles hasta que están a punto de entrar en el viewport del usuario. En lugar de descargar todas las imágenes, vídeos y componentes al cargar la página, solo se carga lo que el usuario va a ver primero. El resto se carga bajo demanda.
El impacto es significativo: páginas con 50 imágenes pueden reducir su carga inicial en un 80% o más. Esto mejora el Largest Contentful Paint (LCP), reduce el consumo de datos móviles y libera ancho de banda y recursos del navegador para el contenido prioritario.
¿Cómo funciona el lazy loading?
El principio es simple: los recursos fuera del viewport se marcan como candidatos a carga diferida. Cuando el usuario hace scroll y el recurso se acerca al área visible, se inicia la descarga. Esto puede implementarse con el atributo HTML nativo loading="lazy", con la Intersection Observer API de JavaScript o con librerías especializadas.
El navegador gestiona la lógica de cuándo iniciar la descarga en el caso nativo: normalmente empieza a cargar cuando el recurso está a unos 1.250 px del viewport en conexiones rápidas y más cerca en conexiones lentas, adaptándose automáticamente a las condiciones del usuario.
Lazy loading de imágenes
Las imágenes son el caso de uso principal del lazy loading porque representan la mayor parte del peso de la mayoría de páginas web. El atributo nativo loading="lazy" en la etiqueta <img> es la implementación más sencilla y eficiente.
- Nativo: <img src="foto.webp" loading="lazy" width="800" height="600" alt="Descripción"> — no requiere JavaScript, soporte universal en navegadores modernos
- Siempre establece width y height para evitar layout shifts (CLS) cuando la imagen se carga
- No apliques lazy loading a la imagen hero o LCP: debe cargarse inmediatamente con fetchpriority="high"
- Para backgrounds en CSS, usa Intersection Observer para añadir la clase con la imagen de fondo cuando el elemento se acerca al viewport
Intersection Observer API
La Intersection Observer API es la forma moderna de implementar lazy loading con JavaScript. Permite observar cuándo un elemento entra o sale del viewport (o de otro contenedor) de forma eficiente, sin los problemas de rendimiento del antiguo enfoque basado en scroll events.
Creas un IntersectionObserver con un callback que se ejecuta cuando los elementos observados cruzan un umbral de visibilidad. El rootMargin permite definir un margen alrededor del viewport para empezar la carga antes de que el elemento sea visible, evitando que el usuario vea un espacio vacío.
- Usa rootMargin para pre-cargar antes de que el elemento sea visible: rootMargin: "200px 0px" carga con 200px de anticipación
- Threshold 0 (por defecto) se activa cuando cualquier píxel del elemento es visible
- Desconecta el observer (unobserve) una vez que el recurso se ha cargado para liberar memoria
- Soporte global >97%: no necesitas polyfill en navegadores modernos
Lazy loading de componentes
Más allá de imágenes, el lazy loading de componentes JavaScript reduce el bundle inicial de la aplicación. Componentes pesados como editores WYSIWYG, mapas interactivos, gráficos o modales complejos pueden cargarse bajo demanda cuando el usuario interactúa con ellos.
React ofrece React.lazy() con Suspense para importar componentes dinámicamente. Vue tiene defineAsyncComponent(). En Astro, las directivas client:visible y client:idle aplican lazy loading nativo a componentes interactivos (islands architecture). Next.js soporta dynamic imports con next/dynamic.
Lazy loading de vídeos e iframes
Los iframes (especialmente de YouTube, Google Maps o embeds de redes sociales) son uno de los recursos más pesados que puede contener una página. Un embed de YouTube carga más de 1 MB de JavaScript y CSS, incluso si el usuario nunca reproduce el vídeo.
- Usa loading="lazy" en iframes: <iframe src="..." loading="lazy"> — soportado nativamente
- Para YouTube: usa lite-youtube-embed o youtube-lite que muestra una miniatura estática y solo carga el reproductor al hacer clic
- Para Google Maps: muestra una imagen estática (Static Maps API) y carga el mapa interactivo al hacer clic o al scroll
- Facading: muestra una versión estática ligera del embed y carga el real solo cuando el usuario interactúa
Impacto en rendimiento y SEO
Lazy loading mejora Core Web Vitals al reducir el peso inicial de la página, pero debe implementarse correctamente para no afectar negativamente al SEO. Googlebot procesa JavaScript y puede renderizar lazy loading basado en Intersection Observer, pero el contenido cargado de forma diferida puede tardar más en indexarse.
Las imágenes con loading="lazy" nativo son indexadas correctamente por Google. Para contenido textual importante, evita lazy loading: el contenido principal debe estar disponible en el HTML inicial para garantizar indexación inmediata. Usa lazy loading solo para recursos below the fold.
- LCP: mejora al reducir la competencia por ancho de banda con la imagen principal
- CLS: puede empeorar si no defines width/height en las imágenes lazy loaded
- INP: mejora al reducir el JavaScript inicial que compite por el hilo principal
- Indexación: Googlebot renderiza lazy loading pero puede tardar más en descubrir contenido diferido
Errores comunes al implementar lazy loading
Lazy loading mal implementado puede empeorar la experiencia en lugar de mejorarla. Los errores más frecuentes incluyen aplicar lazy loading a la imagen LCP (retrasando su carga), no definir dimensiones (causando layout shifts) y usar implementaciones JavaScript pesadas cuando el atributo nativo sería suficiente.
Otro error común es lazy loading demasiado agresivo: si el usuario hace scroll rápido, las imágenes no cargan a tiempo y ve espacios vacíos. Usa rootMargin en Intersection Observer o confía en el comportamiento adaptativo del atributo nativo para mitigar este problema.
Puntos clave
- El atributo loading="lazy" es la forma más simple y eficiente de lazy loading para imágenes
- Nunca apliques lazy loading a la imagen hero/LCP: cárgala con fetchpriority="high"
- Intersection Observer reemplaza los scroll events con rendimiento y control superior
- Los embeds de YouTube y Google Maps son candidatos ideales para lazy loading con facade pattern
- Define siempre width y height en imágenes lazy loaded para evitar layout shifts (CLS)
¿Tu web carga más de lo necesario?
Auditamos tu sitio para identificar oportunidades de lazy loading que mejoren Core Web Vitals y reduzcan el tiempo de carga inicial.