Ver contenido
Mejores Prácticas de Lazy Loading: Cuándo Usarlo y Cuándo NO
Introducción
El lazy loading es una de las técnicas más efectivas para mejorar el rendimiento de páginas—cuando se usa correctamente. Al diferir la carga de imágenes fuera de pantalla, reduces el peso inicial de la página, disminuyes el Time to Interactive (TTI), y ahorras ancho de banda para usuarios que no hacen scroll para ver todo el contenido.
Sin embargo, el lazy loading mal aplicado puede perjudicar el rendimiento en lugar de ayudarlo. El error más crítico es aplicar lazy loading a tu imagen LCP (Largest Contentful Paint), lo que puede agregar más de 500ms a tu Core Web Vital más importante.
Esta guía completa cubre todo lo que necesitas saber sobre implementar lazy loading efectivamente: cuándo usarlo, cuándo evitarlo, estrategias de placeholders, y técnicas avanzadas de optimización.
Entendiendo el Lazy Loading
¿Qué es el Lazy Loading?
El lazy loading difiere la carga de recursos hasta que son necesarios. Para imágenes, esto típicamente significa:
- Las imágenes comienzan como placeholders (vacío, blur, o baja calidad)
- A medida que el usuario hace scroll, las imágenes cerca del viewport activan su carga
- Una vez cargada, la imagen completa reemplaza el placeholder
Beneficios del Lazy Loading
- Carga inicial más rápida: Menos recursos para descargar inicialmente
- Reducción de ancho de banda: Los usuarios solo descargan imágenes que realmente ven
- Menor carga del servidor: Menos solicitudes simultáneas
- Mejor TTI: Menos JavaScript bloqueando por decodificación de imágenes
- Core Web Vitals mejorados: Cuando se aplica correctamente
Lazy Loading Nativo vs JavaScript
Hay dos enfoques principales:
Lazy Loading Nativo (Recomendado):
<img src="foto.jpg" alt="Descripción" loading="lazy">
Lazy Loading con JavaScript:
// Usando Intersection Observer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
El lazy loading nativo ahora está soportado por todos los navegadores principales (97%+ de soporte) y debería ser tu opción predeterminada.
Cuándo Usar Lazy Loading
Candidatos Ideales para Lazy Loading
1. Imágenes Debajo del Fold Cualquier imagen que requiere scroll para ver es un buen candidato:
<!-- Primera pantalla: SIN lazy loading -->
<img src="hero.jpg" alt="Hero">
<!-- Debajo del fold: SÍ lazy loading -->
<img src="producto-2.jpg" alt="Producto" loading="lazy">
<img src="producto-3.jpg" alt="Producto" loading="lazy">
2. Grillas de Productos (Después de la Primera Fila)
<!-- Primera fila visible al cargar -->
<img src="producto-1.jpg" alt="Producto 1">
<img src="producto-2.jpg" alt="Producto 2">
<img src="producto-3.jpg" alt="Producto 3">
<img src="producto-4.jpg" alt="Producto 4">
<!-- Productos restantes: lazy load -->
<img src="producto-5.jpg" alt="Producto 5" loading="lazy">
<img src="producto-6.jpg" alt="Producto 6" loading="lazy">
<!-- ... más productos -->
3. Galerías de Imágenes y Carruseles
<!-- Slide activo: SIN lazy loading -->
<img src="slide-1.jpg" alt="Slide 1" class="active">
<!-- Otros slides: SÍ lazy loading -->
<img src="slide-2.jpg" alt="Slide 2" loading="lazy">
<img src="slide-3.jpg" alt="Slide 3" loading="lazy">
4. Miniaturas de Posts de Blog
<article>
<img src="thumb.jpg" alt="Artículo" loading="lazy">
<h2>Título del Artículo</h2>
</article>
5. Contenido Generado por Usuarios Comentarios, reseñas y feeds sociales frecuentemente contienen muchas imágenes:
<div class="comentario">
<img src="avatar.jpg" alt="Usuario" loading="lazy">
<p>Texto del comentario...</p>
</div>
Cuándo NO Usar Lazy Loading
Casos Críticos a Evitar
1. Imagen LCP (Lo Más Importante)
La imagen Largest Contentful Paint debe cargar inmediatamente:
<!-- INCORRECTO: No uses lazy load en LCP -->
<img src="hero.jpg" alt="Hero" loading="lazy">
<!-- CORRECTO: Sin lazy loading, agrega prioridad -->
<img src="hero.jpg" alt="Hero" fetchpriority="high">
2. Contenido Above-the-Fold
Cualquier cosa visible en la carga inicial de página:
<!-- Todo visible sin scroll: sin lazy loading -->
<header>
<img src="logo.png" alt="Logo de Empresa">
</header>
<main>
<img src="hero.jpg" alt="Hero" fetchpriority="high">
</main>
3. Imágenes Pequeñas (< 10KB)
El overhead del lazy loading puede exceder el ahorro:
<!-- Íconos e imágenes pequeñas: cargar normalmente -->
<img src="icono.svg" alt="" width="24" height="24">
4. Imágenes Críticas de Productos
En páginas de producto de e-commerce, la imagen principal del producto usualmente es LCP:
<!-- Imagen principal de producto: sin lazy loading -->
<img src="producto-principal.jpg" alt="Nike Air Max" fetchpriority="high">
<!-- Galería de miniaturas: lazy load -->
<img src="producto-angulo-2.jpg" alt="Vista lateral" loading="lazy">
<img src="producto-angulo-3.jpg" alt="Vista trasera" loading="lazy">
Estrategias de Placeholder
Buenos placeholders previenen el layout shift mientras comunican que el contenido está cargando.
1. Preservación del Aspect Ratio
Siempre incluye width y height para prevenir CLS:
<img
src="foto.jpg"
alt="Descripción"
width="800"
height="600"
loading="lazy"
>
Con CSS:
img {
aspect-ratio: 4/3;
width: 100%;
height: auto;
}
2. Técnica Blur-Up (LQIP)
Carga una versión diminuta y borrosa primero:
<div class="image-container">
<img
src="foto-tiny.jpg"
data-src="foto.jpg"
alt="Descripción"
class="blur-up"
>
</div>
.blur-up {
filter: blur(20px);
transition: filter 0.3s;
}
.blur-up.loaded {
filter: blur(0);
}
3. Placeholder de Color Sólido
Usa el color dominante de la imagen:
<div class="image-wrapper" style="background: #3498db;">
<img src="foto.jpg" alt="Descripción" loading="lazy">
</div>
4. Skeleton Loaders
Placeholder animado que indica carga:
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 200% 100%;
animation: skeleton 1.5s infinite;
}
@keyframes skeleton {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
Combinando con Priority Hints
Usa fetchpriority junto con lazy loading para resultados óptimos:
<!-- Alta prioridad: imagen LCP -->
<img src="hero.jpg" alt="Hero" fetchpriority="high">
<!-- Prioridad predeterminada: imágenes secundarias above-fold -->
<img src="producto.jpg" alt="Producto">
<!-- Baja prioridad con lazy load: imágenes below-fold -->
<img src="galeria-5.jpg" alt="Galería" loading="lazy" fetchpriority="low">
Prioridad + Preload para Imágenes Críticas
<head>
<!-- Preload de imagen LCP -->
<link rel="preload" as="image" href="hero.webp" type="image/webp">
</head>
<body>
<img src="hero.webp" alt="Hero" fetchpriority="high">
</body>
Umbrales de Carga del Navegador
Los navegadores tienen umbrales incorporados para cuándo las imágenes lazy-loaded comienzan a cargar. Entender estos ayuda a predecir el comportamiento.
Distancia de Carga de Chrome
Chrome comienza a cargar imágenes lazy cuando están dentro de cierta distancia del viewport:
| Velocidad de Conexión | Distancia de Carga |
|---|---|
| 4G | ~1250px |
| 3G | ~2500px |
| 2G | ~6000px |
Esto significa que en conexiones rápidas, las imágenes comienzan a cargar antes; en conexiones lentas, el navegador espera más para ahorrar ancho de banda.
Implicaciones para el Diseño
- Las imágenes en un carrusel pueden comenzar a cargar antes de que el usuario deslice
- El contenido de “scroll infinito” precargará adelante del viewport
- Las páginas muy largas aún se benefician del lazy loading
Lazy Loading y SEO
Comportamiento de Googlebot
Google puede descubrir e indexar imágenes lazy-loaded, pero con advertencias:
- Lazy loading nativo: Completamente soportado por Googlebot
- Lazy loading con JavaScript: Requiere implementación correcta
- Carga activada por scroll: Puede no ser indexada (Googlebot no hace scroll infinitamente)
Mejores Prácticas para SEO
<!-- Incluye src real, no solo data-src -->
<img
src="foto.jpg"
alt="Texto alt descriptivo"
loading="lazy"
>
<!-- MALO: Sin src hasta que JavaScript ejecuta -->
<img
data-src="foto.jpg"
alt="Foto"
src="placeholder.gif"
>
Consideraciones de Datos Estructurados
Para imágenes de productos y otro marcado schema, asegura que la imagen principal cargue sin JavaScript:
<script type="application/ld+json">
{
"@type": "Product",
"image": "https://ejemplo.com/producto.jpg"
}
</script>
Implementación Específica por Framework
Next.js
import Image from 'next/image'
// Imagen LCP: carga eager
<Image src="/hero.jpg" priority alt="Hero" />
// Below-fold: lazy loading (predeterminado)
<Image src="/galeria.jpg" alt="Galería" />
Nuxt
<!-- Imagen LCP -->
<NuxtImg src="/hero.jpg" preload alt="Hero" />
<!-- Lazy loaded (predeterminado) -->
<NuxtImg src="/galeria.jpg" alt="Galería" loading="lazy" />
WordPress
La mayoría de los temas modernos de WordPress aplican lazy loading automáticamente. Para excluir imágenes LCP:
// En functions.php
add_filter('wp_img_tag_add_loading_attr', function($value, $image, $context) {
if (str_contains($image, 'hero-image')) {
return false; // No agregar loading="lazy"
}
return $value;
}, 10, 3);
Midiendo el Impacto del Lazy Loading
Métricas Clave a Rastrear
| Métrica | Qué Medir |
|---|---|
| LCP | Debería mejorar o mantenerse igual (nunca aumentar) |
| TTI | Time to Interactive debería disminuir |
| Total Blocking Time | Debería disminuir |
| Peso de Página | El tamaño de descarga inicial debería disminuir |
| CLS | No debería aumentar (usa aspect ratios) |
Herramientas para Medición
- Lighthouse: Auditoría completa de rendimiento
- Chrome DevTools Network Tab: Ver solicitudes diferidas
- WebPageTest: Vista filmstrip muestra secuencia de carga
- CrUX Dashboard: Datos de usuarios reales a lo largo del tiempo
Errores Comunes y Cómo Corregirlos
1. Todas las Imágenes con Lazy Loading
Problema: CMS o framework aplica lazy loading globalmente Solución: Excluir imágenes de primera pantalla, especialmente LCP
2. Dimensiones Faltantes
Problema: Las imágenes causan layout shift al cargar Solución: Siempre incluir width/height o usar aspect-ratio
3. Umbrales Agresivos
Problema: Las imágenes cargan muy tarde, parpadeo visible Solución: Usar lazy loading nativo o aumentar rootMargin
4. Sin Placeholders
Problema: Espacio vacío salta a espacio lleno Solución: Implementar blur-up, skeleton, o placeholders de color
Checklist de Implementación
- [ ] La imagen LCP NO tiene
loading="lazy" - [ ] La imagen LCP tiene
fetchpriority="high" - [ ] Las imágenes above-fold no tienen lazy loading
- [ ] Las imágenes below-fold tienen
loading="lazy" - [ ] Todas las imágenes lazy tienen atributos width/height
- [ ] Estrategia de placeholder previene layout shift
- [ ] SEO: Las imágenes tienen src real (no solo data-src)
- [ ] Valores predeterminados del framework revisados y ajustados
- [ ] Rendimiento testeado con Lighthouse
Artículos Relacionados
- Lazy Loading de Imagen LCP Explicado - Por qué lazy loading de LCP es incorrecto
- Fetchpriority de Imágenes Explicado - Priority hints para imágenes
- Guía de Preloading de Imágenes - Cuándo hacer preload de imágenes
- Guía de Optimización de CLS - Previniendo layout shift
Referencias
- MDN - atributo loading - Especificación técnica
- web.dev - Browser-level lazy loading - Guía de implementación
- Chrome Developers - Lazy loading images - Documentación Lighthouse
- web.dev - Native lazy loading - Profundización en implementación nativa