Lazy loading de imágenes con Intersection Observer API

Introducción

Veamos en este pequeño tutorial cómo hacer lazy loading de imágenes con Intersection Observer API.

Así evitaremos cargar todas las páginas, sobrecargar nuestros servidores y gastar ancho de banda.

Probar página terminada

Puedes probar aquí la página terminada. Te recomiendo que abras la consola de depuración para ver que las imágenes se cargan conforme navegas.

¿Qué es el lazy loading?

El lazy loading es cargar las imágenes de una página web conforme el usuario las necesite.

Es decir, si tenemos una página con 100 imágenes el usuario no verá las 100 al mismo momento, sino que tal vez irá bajando poco a poco. Justo ahí entra en acción el observador de intersección, que nos dirá si el usuario está a punto de ver la imagen. En caso de que sí, la cargamos.

¿Qué es intersection observer API?

Es una nueva API de programación de JavaScript que nos dice si la pantalla visible del usuario está a punto de intersecar con algo.

Tiene múltiples usos, pero veremos cómo hacerlo para cargar imágenes conforme el usuario hace scroll.

Hace tiempo, cuando esta API no existía, no tengo idea de cómo se hacía pero supongo que se vigilaba el scroll, la altura del documento y muchísimas cosas más.

Pues Intersection observer viene a solucionarnos este problema. Ah, por cierto, recordemos que necesitamos un navegador actualizado.

Actualmente es compatible con Edge 12, Firefox y Chrome en sus últimas versiones. Puedes ver la lista aquí.

Ventajas

Como lo dije, ahorramos ancho de banda porque no requerimos todas las imágenes al mismo tiempo sin que el usuario las vaya a ver.

Y por otro lado, la página cargará más rápido.

Pero bueno, vamos allá.

Lazy loading de imágenes con Intersection Observer API

Lo que haremos será una simple página con texto e imágenes. Y las imágenes serán cargadas conforme el usuario haga scroll o navegue.

Documento HTML

Entonces tenemos nuestro documento HTML que queda así:

No prestemos atención a otra cosa que la imagen. Vemos que no tiene src, sino data-src. Esto es porque no queremos que el navegador descargue la imagen, dejamos vacío el atributo y ponemos la verdadera imagen en un atributo que el navegador no conoce; bueno, sí lo conoce pero no descargará la imagen de ahí.

Por otro lado vemos que la imagen tiene la clase lazy-loading. Esto es para que luego podamos recuperarlas a todas con querySelectorAll.

Es importante mencionar que vamos a repetir muchas veces el div. En el código de arriba no se repite porque sería muy largo pegarlo aquí en el post, pero vamos a repetirlo para que haya muchas imágenes y scroll.

Se darán cuenta de que lo cargamos de https://picsum.photos/200 (un servicio que da imágenes para probar). Pues podemos cambiar el 200 por otro número y ese será el tamaño de la imagen en pixeles.

Adicionalmente podemos anexar otro número después del 200 (por ejemplo 200/100) para la otra medida.

Recuperar imágenes

Ahora vamos a recuperar todas las imágenes que tengan la clase lazy-loading. Para ello esperaremos el evento DOMContentLoaded que es como el document ready de jQuery.

Más tarde usamos document.querySelector y le pasamos el selector de img que tenga la clase lazy-loading (img.lazy-loading)

Te preguntarás por qué pongo un $ antes del nombre de la variable. Y es porque tengo la costumbre de que a los elementos del DOM les pongo dicho símbolo para identificarlos como elementos, no como variables que uso en el programa.

Es una práctica mía, no importa el nombre

Comprobar IntersectionObserver y observar

Ahora comprobamos si el navegador tiene soporte para observar la intersección. Y en caso de que sí, creamos un observador y por cada entrada que tenga añadimos un callback.

Dicho callback es llamado cuando hay una intersección con un elemento.

Comparamos si el ratio es mayor a 0 (lo que significa que el usuario va a ver la imagen) y a la imagen le ponemos el atributo src copiando lo que había en data-src:

Por cierto, en caso de que no exista la API en el navegador entonces cargamos la fuente de la imagen normalmente; es decir, no hay lazy-loading pero las imágenes sí se verán (aunque cargarán de modo convencional)

Finalmente dejamos de observar a la imagen con:

observador.unobserve(imagen);

Porque una vez cargada la imagen ya no necesitaremos vigilarla.

Observar imágenes

Ya programamos el callback de la imagen y dijimos que la imagen será cargada y dejada de observar. Lo único que falta ahora es observarlas para que dicho callback sea llamado:

Con eso vamos a observar cada imagen.

Código completo

El código completo de ejemplo queda así:

Y con eso, cualquier imagen que tenga la clase será cargada con lazy-loading.

Probar documento

Si ahora abrimos nuestro documento, abrimos la consola y navegamos, veremos que la imagen se irá cargando conforme hacemos scroll o mejor dicho, mientras navegamos ya sea con el teclado, el touch o el mouse.

Informe de imagen cargada con Lazy Loading
Informe de imagen cargada con Lazy Loading

Recuerda que puedes probar el proyecto terminado en mi página web.

Así es como podemos hacer lazy loading de imágenes con JavaScript sin quebrarnos la cabeza.

Puedes también, en la consola, abrir la pestaña de Network y ver que las imágenes no se cargan al mismo tiempo.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

3 comentarios en “Lazy loading de imágenes con Intersection Observer API”

    1. Me parece que no es recomendable usar srcset con JavaScript. Lo recomendable sería usar algo así como el lazy loading pero detectar el tamaño de la pantalla del dispositivo y a partir de ello cargar una imagen con el tamaño apropiado

  1. Pingback: He renovado mi página principal y ahora es open source - Parzibyte's blog

Dejar un comentario