Guía detallada

Lazy Loading Best Practices Guide

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:

  1. Las imágenes comienzan como placeholders (vacío, blur, o baja calidad)
  2. A medida que el usuario hace scroll, las imágenes cerca del viewport activan su carga
  3. 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:

  1. Lazy loading nativo: Completamente soportado por Googlebot
  2. Lazy loading con JavaScript: Requiere implementación correcta
  3. 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

  1. Lighthouse: Auditoría completa de rendimiento
  2. Chrome DevTools Network Tab: Ver solicitudes diferidas
  3. WebPageTest: Vista filmstrip muestra secuencia de carga
  4. 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


Referencias

  1. MDN - atributo loading - Especificación técnica
  2. web.dev - Browser-level lazy loading - Guía de implementación
  3. Chrome Developers - Lazy loading images - Documentación Lighthouse
  4. web.dev - Native lazy loading - Profundización en implementación nativa

Artículos relacionados

Versión relacionada

Introducción

Lcp Image Lazy Loading Explained

El lazy loading de imágenes es ampliamente considerado una mejor práctica para el rendimiento web

Hub de categoría

Hub

Images Seo Hub

Las imágenes son críticas para el engagement del usuario, pero también pueden ser el mayor cuello de botella de rendimiento de tu sitio web

En la misma categoría

Guía detallada

Responsive Images Implementation Guide

Las imágenes responsivas son una de las optimizaciones de rendimiento más impactantes que puedes implementar

Guía detallada

Image Optimization Guide

Las imágenes típicamente representan la mayor porción de bytes descargados en una página web

Otros temas

Guía detallada

Lcp Optimization Guide

Largest Contentful Paint (LCP) mide cuándo el elemento de contenido más grande se vuelve visible para los usuarios