web

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í:

See the gist on github.

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)

See the gist on github.

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:

See the gist on github.

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:

See the gist on github.

Con eso vamos a observar cada imagen.

Código completo

El código completo de ejemplo queda así:

See the gist on github.

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

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.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Ver comentarios

  • Muy interesante tu código, no tienes uno que funcione con srcset ? he visto varios pero todos muy enredados

    • 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

Entradas recientes

Imprimir PDF con Bot de Telegram

La impresión de un PDF en cualquier impresora se puede automatizar con un bot de…

12 horas hace

Enviar mensaje con bot de Telegram usando JavaScript (lado del cliente)

Hoy te enseñaré cómo enviar un mensaje a un usuario desde un bot de Telegram…

1 día hace

PHP: incrustar imagen en base64

El día de hoy te enseñaré algo muy sencillo pero útil al programar con PHP:…

1 día hace

Plugin ESC POS – Actualización 3.4.0: imprimir HTML

El plugin para imprimir en impresoras térmicas alcanza hoy su versión 3.4.0 agregando soporte para…

2 días hace

JavaScript (lado del cliente): leer pixeles de imagen

En ocasiones es necesario leer los pixeles y colores de una imagen con JavaScript del…

1 semana hace

PHP y JavaScript: llenar select con AJAX

Siguiendo con los tutoriales de listas desplegables o select con JavaScript, vamos a ver cómo…

1 semana hace

Esta web usa cookies.