Carga diferida de imágenes

Las imágenes pueden aparecer en una página web porque están intercaladas en el HTML como elementos <img> o como imágenes de fondo CSS. En esta publicación, descubrirás cómo realizar una carga diferida en ambos tipos de imágenes.

Imágenes intercaladas

Los candidatos más comunes para la carga diferida son las imágenes que se usan en los elementos <img>. Las imágenes intercaladas tienen tres opciones de carga diferida: que pueden combinarse para obtener la mejor compatibilidad con los navegadores:

Usa la carga diferida a nivel del navegador

Tanto Chrome como Firefox admiten la carga diferida con el atributo loading. Este atributo se puede agregar a los elementos <img> y también a los elementos <iframe>. Un valor de lazy le indica al navegador que cargue la imagen de inmediato si está en el viewport. y para recuperar otras imágenes cuando el usuario se desplaza cerca de ellas.

Consulta el campo loading de los MDN compatibilidad de navegadores para obtener detalles sobre la compatibilidad del navegador. Si el navegador no admite la carga diferida, se ignorará el atributo. y las imágenes se cargarán inmediatamente, como de costumbre.

Para la mayoría de los sitios web, agregar este atributo a las imágenes intercaladas mejora el rendimiento. y permite que los usuarios carguen imágenes a las que quizás nunca desplacen. Si tienes una gran cantidad de imágenes y quieres asegurarte de que los usuarios de navegadores incompatibles no admitan la carga diferida deberás combinar esto con uno de los métodos que se explican a continuación.

Para obtener más información, consulta Carga diferida a nivel del navegador para la Web.

Cómo usar Intersection Observer

Para la carga diferida de polyfills de elementos <img>, usamos JavaScript para verificar si están en el viewport. Si es así, sus atributos src (y, a veces, srcset) son los siguientes: se complete con URLs que dirijan al contenido de imagen deseado.

Si ya escribiste código de carga diferida, es posible que hayas completado la tarea. mediante controladores de eventos, como scroll o resize Si bien este enfoque es más compatibles con los navegadores, los navegadores modernos ofrecen una mayor eficiente de cómo verificar la visibilidad de los elementos a través de la API de Intersection Observer.

Intersection Observer es más fácil de usar y leer que el código que se basa en varios controladores de eventos, ya que solo debes registrar un observador para en lugar de escribir un código de detección de visibilidad de elementos tedioso. Todo queda decidir qué hacer cuando un elemento es visible. Supongamos que este es el patrón de lenguaje de marcado básico para tus elementos <img> de carga diferida:

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">

Hay tres partes relevantes de este lenguaje de marcado en las que debes enfocarte:

  1. El atributo class, que es lo que seleccionarás el elemento en JavaScript:
  2. El atributo src, que hace referencia a una imagen de marcador de posición que aparecerá cuando de que la página se cargue primero.
  3. Los atributos data-src y data-srcset, que son atributos de marcador de posición que contiene la URL de la imagen que cargarás una vez que el elemento esté en el viewport.

Ahora, veamos cómo usar Intersection Observer en JavaScript para la carga diferida con este patrón de marcado:

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Possibly fall back to event handlers here
  }
});

En el evento DOMContentLoaded del documento, esta secuencia de comandos consulta el DOM para todos los Elementos <img> con una clase de lazy. Si Intersection Observer está disponible, crea un nuevo observador que ejecute una devolución de llamada cuando los elementos img.lazy ingresen al viewport.

Intersection Observer está disponible en todos los navegadores actualizados. Por lo tanto, usarlo como polyfill para loading="lazy" garantizará que la carga diferida esté disponible para la mayoría de los visitantes.

Imágenes en CSS

Si bien las etiquetas <img> son la forma más común de usar imágenes en páginas web, las imágenes también puede invocarse a través del código CSS background-image propiedad (y otras propiedades). La carga diferida a nivel del navegador no se aplica a las imágenes de fondo de CSS por lo que deberás considerar otros métodos si cuentas con imágenes de fondo para carga diferida.

A diferencia de los elementos <img>, que se cargan de su visibilidad, el comportamiento de carga de imágenes en CSS la especulación. Cuando el documento y el objeto CSS personalizados y renderizar árbol el navegador examina cómo se aplica CSS a un documento antes solicitar recursos externos. Si el navegador determinó una regla CSS que involucra un recurso externo no se aplica al documento como está actualmente construido, el navegador no lo solicita.

Este comportamiento especulativo puede usarse para diferir la carga de imágenes en CSS usar JavaScript para determinar cuándo un elemento se encuentra dentro del viewport y, luego, aplicar una clase a ese elemento que aplique un estilo invocando un imagen de fondo. Esto hará que la imagen se descargue cuando se necesite. en lugar de en la carga inicial. Por ejemplo, tomemos un elemento que contiene un imagen de fondo hero grande:

<div class="lazy-background">
  <h1>Here's a hero heading to get your attention!</h1>
  <p>Here's hero copy to convince you to buy a thing!</p>
  <a href="/buy-a-thing">Buy a thing!</a>
</div>

En general, el elemento div.lazy-background contendría el fondo hero imagen invocada por algún CSS. Sin embargo, en este ejemplo de carga diferida, La propiedad background-image del elemento div.lazy-background a través de un visible que se agrega al elemento cuando está en el viewport:

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

Desde aquí, usa JavaScript para verificar si el elemento está en el viewport (con Intersection Observer) y agregar la clase visible al div.lazy-background en ese momento, que carga la imagen:

document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
});

Efectos en el Procesamiento de imagen con contenido más grande (LCP)

La carga diferida es una excelente optimización que reduce el uso general de datos y la contención de red durante el inicio aplazando la carga de las imágenes hasta cuando sean realmente necesarias. Esto puede mejorar el tiempo de inicio y reducir el procesamiento en el subproceso principal, ya que reduce el tiempo necesario para las decodificación de imágenes.

Sin embargo, la carga diferida es una técnica que puede afectar de forma negativa el LCP de pintura con contenido más grande de tu sitio web si te interesa mucho la técnica. Una cosa que debes evitar es la carga diferida de imágenes que se encuentran en el viewport durante el inicio.

Cuando uses cargadores diferidos basados en JavaScript, evita la carga diferida de imágenes en el viewport, ya que estas soluciones suelen usar un atributo data-src o data-srcset como marcador de posición para los atributos src y srcset. El problema es que se retrasará la carga de estas imágenes porque el análisis de precarga del navegador no puede encontrarlas durante el inicio.

Incluso la carga diferida a nivel del navegador para la carga diferida de una imagen en el viewport puede tener consecuencias negativas. Cuando se aplica loading="lazy" a una imagen en el viewport, esa imagen se retrasa hasta que el navegador sabe con seguridad que está en el viewport, lo que puede afectar el LCP de una página.

Nunca cargues de forma diferida las imágenes que sean visibles en el viewport durante el inicio. Es un patrón que afectará de forma negativa al LCP de tu sitio y, por lo tanto, a la experiencia del usuario. Si necesitas una imagen durante el inicio, cárgala lo más rápido posible sin una carga diferida.

Carga diferida de bibliotecas

Debes usar la carga diferida a nivel del navegador siempre que sea posible. Sin embargo, si te encuentras en una situación en la que no es posible, como un grupo significativo de usuarios que todavía depende de navegadores más antiguos, puedes usar las siguientes bibliotecas para cargar imágenes de forma diferida:

  • lazysizes es un formato perezoso con todas las funciones que carga de forma diferida las imágenes y los iframes. El patrón que usa es bastante similar a los ejemplos de código que se muestran aquí, en que se vincula automáticamente a una lazyload en elementos <img> y requiere que especifiques las URLs de imágenes en Atributos data-src o data-srcset, cuyo contenido está intercambiado en atributos src o srcset, respectivamente. Usa Intersección Observer (que se puede aplicar en polyfill) y se puede extender con varias versiones complementos hacer cosas como videos de carga diferida. Obtenga más información sobre el uso de tamaños diferidos.
  • vanilla-lazyload es una opción ligera para imágenes de carga diferida, imágenes de fondo, videos, iframes, y secuencias de comandos. Aprovecha Intersection Observer, admite imágenes responsivas y habilita la carga diferida a nivel del navegador.
  • lozad.js es otra clase de que solo usa Intersection Observer. Por eso, tiene un alto rendimiento pero deberá tener polyfill para poder utilizarla en navegadores anteriores.
  • Si necesitas una biblioteca de carga diferida específica para React, considera react-lazyload) Si bien no usa Intersection Observer; proporciona un método familiar de inactividad cargando imágenes para quienes están acostumbrados a desarrollar aplicaciones con React.