Webability
Rendimiento SEO Arquitectura 30 de abril de 2026 · 10 min de lectura

Lazy loading:
el secreto para que tu sitio cargue volando (y por qué Google lo premia)

El lazy loading es, sin exagerar, la técnica más rentable que existe para acelerar un sitio web. No requiere reescribir la app, no necesita un servidor potente y, mejor aún, es completamente independiente del proveedor de imágenes que uses. Aquí explicamos por qué importa tanto y cómo implementarlo sin amarrarte a nadie.

1. Qué es el lazy loading (y por qué es tan importante)

Lazy loading —"carga perezosa" en español— es una técnica sencilla con un impacto enorme: en lugar de descargar todas las imágenes de una página al mismo tiempo cuando el usuario llega, el navegador descarga solo lo que está a punto de ser visible. El resto se descarga conforme el usuario hace scroll.

Piensa en una página típica: un hero con una foto de portada, tres secciones intermedias y una galería al final con doce imágenes. Sin lazy loading, el navegador pide las dieciséis imágenes antes de que el usuario haya visto siquiera la primera línea. Con lazy loading, descarga la del hero (la única visible) y deja el resto para después. El usuario empieza a ver tu página inmediatamente.

💡

La regla del primer pantallazo

En la mayoría de los sitios, el usuario solo ve entre el 15% y el 30% del contenido total de una página. Si descargas únicamente lo que ve, en lugar de todo, estás bajando el peso inicial entre 3 y 6 veces sin tocar nada más.

Y lo mejor: el lazy loading es una técnica completamente del lado del cliente. Vive en tu HTML y en una pequeña pieza de JavaScript (o incluso solo en HTML moderno con loading="lazy"). No depende del backend, no depende del CDN y, sobre todo, no depende del proveedor de imágenes que uses.

2. El impacto real en la velocidad de navegación

El número que importa al usuario es uno solo: cuánto tarda en ver y poder usar la página. El lazy loading mueve esa aguja de manera dramática porque ataca el problema más caro de toda página web: descargar bytes que el usuario nunca verá.

Métrica Sin lazy loading Con lazy loading Mejora típica
Peso inicial descargado 8 – 12 MB 1 – 2 MB 5 – 8× menos
Tiempo hasta ver contenido (LCP) 4 – 7 seg 0.8 – 1.5 seg 3 – 5× más rápido
Peticiones HTTP iniciales 40 – 80 8 – 15 5× menos
Datos consumidos por usuario que no llega al footer 100% del peso ⚠️ solo lo visto factura del CDN

Hay un beneficio adicional que pocos mencionan: el lazy loading también te ahorra dinero. Si pagas por ancho de banda en tu CDN o por transformaciones en un proveedor de imágenes, no descargar lo que el usuario no verá significa menos facturación. Para un sitio con tráfico moderado, esto puede traducirse en cientos de dólares mensuales.

El multiplicador del scroll: en un blog largo o una landing extensa, los usuarios típicamente solo llegan al 40-60% del contenido. Eso significa que casi la mitad de las imágenes nunca son vistas. Sin lazy loading, las descargaste todas. Con lazy loading, solo entregaste lo que el usuario quiso ver.

3. Por qué Google lo recompensa en el ranking

Google no esconde sus criterios: desde 2021 los Core Web Vitals son señal oficial de ranking. Y dos de esas tres métricas se mejoran prácticamente solas cuando aplicas lazy loading correctamente.

🎯

LCP

Largest Contentful Paint

Al no competir con decenas de imágenes que el usuario ni va a ver, la imagen principal del hero llega al navegador antes. El LCP cae entre un 40% y un 70% en sitios bien implementados.

INP

Interaction to Next Paint

Menos imágenes en cola significa menos trabajo del navegador para decodificar y pintar. La página responde más rápido a clicks y taps mientras carga.

📊

Crawl budget

Indexación de Google

Googlebot también es un visitante. Un sitio rápido permite que el bot indexe más páginas por sesión y vuelva más seguido. Resultado: tu contenido nuevo se indexa antes.

Google no se limita a recomendar lazy loading — lo trae incorporado de fábrica en Chrome a través del atributo loading="lazy". Cuando ves esa directiva en una etiqueta <img>, es exactamente lo que el equipo de Chrome quiere que hagas.

Dato clave: En PageSpeed Insights, una de las recomendaciones más frecuentes para mejorar el LCP es literalmente "Defer offscreen images" — diferir las imágenes fuera de pantalla. Eso es lazy loading. Si tu sitio marca rojo en esa categoría, lazy loading es la solución directa.

4. La independencia: por qué no debes amarrarte a un proveedor

Aquí viene la parte que pocos artículos abordan honestamente: el lazy loading es una técnica de cliente, no una funcionalidad de un proveedor. Vive en tu HTML y en tu JavaScript. Funciona perfectamente sin ningún proveedor externo.

Esto importa porque en producción real las cosas cambian: un día contratas un servicio de imágenes a la carta como Webability, Cloudinary o Imgix. Otro día decides cambiar de proveedor o llevarlo in-house. Si tu lazy loading está bien diseñado, ese cambio es cuestión de minutos y no toca tu HTML.

Las dos capas que conviene mantener separadas

Capa 1 — Lazy loading (tu código)

  • Decide cuándo cargar una imagen
  • Vive en tu HTML y un script propio
  • Se basa en IntersectionObserver
  • No conoce a tu proveedor

Capa 2 — Optimización (el proveedor)

  • Decide qué versión entregar
  • Vive en la URL de la imagen
  • Resuelve formato, tamaño y compresión
  • Es opcional y reemplazable

Si las dos capas se diseñan independientes, puedes activar/desactivar el proveedor con un solo cambio en la URL base. Si las mezclas (por ejemplo, dependiendo del SDK de un proveedor para detectar cuándo cargar), te amarras y cambiar duele.

En las siguientes secciones vamos a ver código concreto de las tres situaciones reales: primero un lazy loading que funciona solo, luego cómo conectarle un proveedor, y finalmente cómo desconectarlo cuando ya no lo necesitas — sin tocar el HTML.

5. Ejemplo: lazy load independiente (sin proveedor)

Empecemos por lo más limpio: un lazy loading que no depende de nadie. Tu sitio sirve sus propias imágenes y tú decides cuándo cargarlas.

El truco es siempre el mismo: no pongas la URL real en el atributo src. Ponla en data-src, y deja que un pequeño script la mueva al src en el momento adecuado.

El HTML

<!-- Imágenes con lazy load propio -->
<img class="lazy"
     data-src="/images/foto-1.jpg"
     width="800" height="600"
     alt="Vista del producto">

<img class="lazy"
     data-src="/images/foto-2.jpg"
     width="800" height="600"
     alt="Detalle del producto">

Nota cómo no hay src: solo data-src. El navegador no dispara la descarga automáticamente. Y los atributos width y height reservan el espacio para evitar saltos visuales (CLS).

El script (sin librerías)

// lazy.js — versión independiente, ~20 líneas, sin dependencias
(function () {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (!entry.isIntersecting) return;
      const img = entry.target;
      // Mueve la URL real al src — el navegador descarga ahora.
      img.src = img.dataset.src;
      img.removeAttribute('data-src');
      img.classList.remove('lazy');
      img.classList.add('lazy-loaded');
      observer.unobserve(img);
    });
  }, {
    rootMargin: '200px 0px',  // empieza a cargar 200px antes de ser visible
    threshold: 0.01
  });

  document.querySelectorAll('img.lazy').forEach((img) => observer.observe(img));
})();

Eso es todo. Veinte líneas, cero dependencias, cero proveedores. Cualquier imagen con clase lazy se carga solo cuando entra (o está a punto de entrar) en pantalla. Y si el navegador no soporta IntersectionObserver —caso extremadamente raro hoy— la imagen simplemente nunca se carga, lo cual es bastante seguro como degradación. Para una protección extra, puedes incluir un fallback que cargue todo si el observer no existe.

Punto clave: el HTML solo conoce /images/foto-1.jpg. No sabe nada de proveedores, transformaciones ni formatos. Eso es lo que lo hace portátil.

6. Ejemplo: conectar el lazy load a un proveedor

Llega el día en que quieres entregar WebP a Chrome, AVIF a Safari, redimensionar al vuelo para cada dispositivo y servir desde un CDN global. Es decir: contratar un proveedor de imágenes a la carta.

Si tu HTML está bien diseñado, no tocas el HTML. Solo cambias el script. El truco es que el script construya la URL del proveedor a partir del data-src que ya tenías.

El HTML — exactamente igual que antes

<!-- Mismo HTML que en el ejemplo anterior. No cambia nada. -->
<img class="lazy"
     data-src="/images/foto-1.jpg"
     data-width="800"
     width="800" height="600"
     alt="Vista del producto">

Si quieres que el proveedor pueda redimensionar, agrega data-width con el ancho real al que se renderiza. Eso permite que el script pida la versión correcta para cada dispositivo.

El script — ahora con proveedor

// lazy.js — versión conectada a un proveedor (Webability como ejemplo)
(function () {
  const PROVIDER  = 'https://cdn.webability.info';   // base del proveedor
  const ACCOUNT   = 'mi-cuenta';                     // tu identificador
  const dpr       = window.devicePixelRatio || 1;    // soporte retina

  // Función que transforma "/images/foto.jpg" en una URL del proveedor.
  function buildUrl(originalSrc, width) {
    const w = Math.round(width * dpr);
    return `${PROVIDER}/${ACCOUNT}/w_${w},f_auto,q_auto${originalSrc}`;
  }

  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      if (!entry.isIntersecting) return;
      const img      = entry.target;
      const original = img.dataset.src;
      const width    = parseInt(img.dataset.width || img.width || 800, 10);

      // Aquí está la única línea que cambia respecto al ejemplo independiente:
      img.src = buildUrl(original, width);

      img.removeAttribute('data-src');
      img.classList.remove('lazy');
      img.classList.add('lazy-loaded');
      observer.unobserve(img);
    });
  }, { rootMargin: '200px 0px', threshold: 0.01 });

  document.querySelectorAll('img.lazy').forEach((img) => observer.observe(img));
})();

Una sola función nueva —buildUrl()— y una línea modificada. El HTML sigue diciendo /images/foto-1.jpg; el script es el que decide convertir esa URL en https://cdn.webability.info/mi-cuenta/w_800,f_auto,q_auto/images/foto-1.jpg en el momento de la descarga. El navegador recibe AVIF si lo soporta, WebP si no, y el tamaño exacto para la pantalla del usuario.

Lo importante: agregar el proveedor no rompió nada. Si mañana borras el script y vuelves al de la sección 5, las imágenes siguen funcionando — solo que sin transformación. Tu HTML está intacto.

7. Ejemplo: desconectar el proveedor sin romper nada

Imagina el escenario inverso: hace seis meses arrancaste con un proveedor, integraste todo, y ahora quieres cambiar de proveedor o servir tú mismo las imágenes. Si seguiste la receta de la sección anterior, esto es trivial.

Para "apagar" el proveedor, simplemente reemplaza lazy.js con la versión independiente:

Cambiar a otro proveedor

// lazy.js — la nueva función buildUrl con otro proveedor.
// El resto del archivo es idéntico: el observer no cambia,
// el HTML no cambia, los data-src no cambian.

function buildUrl(originalSrc, width) {
  // Antes: Webability
  // return `https://cdn.webability.info/mi-cuenta/w_${width},f_auto,q_auto${originalSrc}`;

  // Ahora: otro proveedor
  return `https://otro-proveedor.cdn.com/fit-in/${width}x0/filters:format(auto)${originalSrc}`;
}

Apagar el proveedor por completo

// Para volver a servir desde tu propio dominio,
// simplemente devuelve la URL original sin tocarla.

function buildUrl(originalSrc, width) {
  return originalSrc;   // adiós proveedor.
}

Eso es todo. Una función que devuelve un string. El HTML del sitio nunca se tocó: sigue teniendo data-src="/images/foto.jpg" como el primer día. Las miles de páginas, los miles de productos, los miles de artículos siguen funcionando. La migración entre proveedores es un solo archivo JavaScript.

El patrón de oro

  1. El HTML guarda la URL "lógica" de la imagen (por ejemplo, /images/foto.jpg).
  2. El JavaScript decide cuándo cargarla y cómo transformarla en una URL real.
  3. El proveedor es una decisión exclusiva del JavaScript. Cambiarlo, agregarlo o quitarlo nunca toca el HTML.

Cuando estas tres reglas se respetan, el lazy loading deja de ser una "feature de un proveedor" y se convierte en una capa propia, portátil y eterna de tu sitio.

8. Buenas prácticas y errores comunes

✓ Sí hacer

  • Reservar espacio con width y height para evitar layout shifts (CLS).
  • Usar rootMargin de 100-200px para empezar la carga antes de ser visible.
  • Excluir del lazy loading las imágenes above the fold (sobre todo el hero/LCP).
  • Mantener data-src con la URL lógica, sin parámetros del proveedor.

✗ No hacer

  • Aplicar lazy loading a la imagen del hero — empeora el LCP en lugar de mejorarlo.
  • Hardcodear las URLs del proveedor en el HTML. Te amarras y cambiar duele.
  • Olvidar el atributo alt: SEO y accesibilidad sufren.
  • Cargar TODAS las imágenes a la vez con un solo trigger. Pierdes el beneficio.

Un detalle importante: la imagen del hero —la que carga primero y define tu LCP— debería usar el atributo nativo fetchpriority="high" en lugar de lazy loading. Hacer lazy loading sobre el hero es contraproducente: es la única imagen que el usuario sí ve inmediatamente.

Y para todo lo demás —galerías, sliders, contenido secundario, footers— el lazy loading es no negociable. Es la diferencia entre una página que aparece al instante y una que hace esperar.

9. Referencias y lecturas recomendadas

Las fuentes oficiales y técnicas más sólidas para profundizar en el tema:

Webability · Blog

Última actualización: 30 de abril de 2026

← Ver todos los artículos