Lazy loading immagini: 5 metodi per pagine più veloci

Lazy loading immagini: 5 metodi per pagine più veloci

Le immagini sono tra i contenuti più diffusi sul web, e il tempo di caricamento delle pagine diventa in fretta un problema.

Anche quando sono ottimizzate come si deve, le immagini pesano parecchio. Il risultato è un’attesa più lunga prima che i visitatori raggiungano il contenuto del sito. Molti si spazientiscono e vanno altrove, a meno che tu non trovi un modo di caricare le immagini che non intacchi la velocità percepita.

In questo articolo scoprirai cinque approcci al lazy loading delle immagini da aggiungere alla tua cassetta degli attrezzi per l’ottimizzazione web e migliorare l’esperienza utente sul tuo sito.

Che cos’è il lazy loading?

Il lazy loading delle immagini consiste nel caricarle in modo asincrono, cioè dopo il resto del contenuto, o addirittura in modo condizionato, solo quando compaiono nella finestra del browser. Vuol dire che se l’utente non scorre fino in fondo alla pagina, le immagini piazzate in basso non vengono nemmeno caricate.

Parecchi siti usano questo approccio, ma si nota soprattutto su quelli ricchi di immagini. Prova a sfogliare il tuo archivio preferito di foto ad alta risoluzione e ti accorgerai in fretta che il sito carica solo un numero limitato di immagini. Mentre scorri, vedrai i segnaposto riempirsi rapidamente con le immagini vere dell’anteprima. Guarda per esempio il caricamento su Unsplash.com: portare quella parte della pagina in vista sostituisce il segnaposto con la foto a piena risoluzione.

Perché interessarsi al lazy loading delle immagini?

Ci sono almeno due ottime ragioni per usare immagini caricate in lazy loading sul tuo sito:

  • Se il tuo sito si appoggia a JavaScript per mostrare contenuti o offrire una qualsiasi funzionalità agli utenti, il caricamento del DOM diventa in fretta critico. È normale che gli script aspettino il DOM completamente caricato prima di partire. Su un sito con molte immagini, il lazy loading – cioè il caricamento asincrono delle immagini – può fare la differenza tra un utente che resta e uno che se ne va.
  • Dato che la maggior parte delle soluzioni di lazy loading carica le immagini solo se l’utente scorre fino al punto in cui sarebbero visibili nel viewport, quelle immagini non vengono mai caricate se quel punto non viene mai raggiunto. Sono risparmi di banda notevoli, e la maggior parte degli utenti, soprattutto chi naviga da mobile e su connessioni lente, te ne sarà grata.

Il lazy loading delle immagini aiuta le prestazioni di un sito, ma qual è il modo migliore per metterlo in pratica?

Non esiste un metodo perfetto.

Se vivi di JavaScript, scrivere la tua soluzione di lazy loading non sarà un problema. Niente dà più controllo del codice che hai scritto tu.

Puoi anche cercare in giro per il web approcci già collaudati e sperimentarli. È quello che ho fatto io, e ho trovato queste cinque tecniche interessanti.

#1 Lazy loading nativo

Il lazy loading nativo di immagini e iframe è una gran cosa. Niente di più semplice del markup qui sotto:

markup
<img src="myimage.jpg" loading="lazy" alt="..." />
<iframe src="content.html" loading="lazy"></iframe>

Come vedi, niente JavaScript, nessuno scambio dinamico dell’attributo src di immagini e iframe: solo buon vecchio HTML.

L’attributo loading permette di rimandare le immagini e gli iframe fuori schermo finché l’utente non scorre fino al punto in cui si trovano nella pagina. loading accetta uno di questi tre valori:

  • lazy: la scelta giusta per il lazy loading
  • eager: chiede al browser di caricare subito il contenuto indicato.
  • auto: lascia al browser la decisione di applicare o meno il lazy loading.

Questo metodo non ha rivali: nessun costo aggiuntivo, pulito e semplice. Però, anche se al momento in cui scriviamo la maggior parte dei browser principali offre un buon supporto per l’attributo loading, non tutti i browser sono ancora allineati.

#2 Lazy loading con l’API Intersection Observer

L’API Intersection Observer è un’interfaccia moderna che puoi usare per il lazy loading di immagini e di altri contenuti.

Ecco come MDN presenta questa API:

L’API Intersection Observer permette di osservare in modo asincrono le variazioni dell’intersezione di un elemento target con un elemento antenato o con il viewport di un documento di primo livello.

In altre parole, quello che si osserva in modo asincrono è l’intersezione di un elemento con un altro.

Immagina di voler caricare in lazy loading una galleria di immagini. Il markup di ogni immagine sarebbe così:

markup
<img data-src="image.jpg" alt="test image">

Noterai che il percorso dell’immagine sta in un attributo data-src e non in un attributo src. Il motivo è semplice: con src l’immagine verrebbe caricata subito, e non è quello che vuoi.

Nel CSS dai a ogni immagine una min-height, diciamo 100px. Così ogni slot immagine (l’elemento img senza attributo src) ha una dimensione verticale:

css
img {
min-height: 100px;
/* altri stili qui */
}

Nel file JavaScript crei poi un oggetto config e lo registri con un’istanza di intersectionObserver:

javascript
// creare un oggetto di configurazione: rootMargin e threshold
// sono due proprietà esposte dall'interfaccia
const config = {
  rootMargin: '0px 0px 50px 0px',
  threshold: 0
};

// registrare l'oggetto config con un'istanza
// di intersectionObserver
let observer = new intersectionObserver(function(entries, self) {
// iterare su ogni entry
  entries.forEach(entry {
    // elaborare solo le immagini in intersezione.
    // isIntersecting è una proprietà esposta dall'interfaccia
if(entry.isIntersecting) {
    /. / Fonction personnalisée qui copie le chemin vers l'image
      // da data-src a src
preloadImage(entry.target);
      // l'immagine è a posto, smetti di osservarla
      self.unobserve(entry.target);
}
});
}, config);

Infine scorri tutte le tue immagini e le aggiungi a questa istanza di iterationObserver:

javascript
const imgs = document.querySelectorAll('[data-src]');
imgs.forEach(img {
  observer.observe(img);
});

I vantaggi di questa soluzione: è semplice da mettere in piedi, è efficiente e lascia a intersectionObserver il grosso del lavoro di calcolo.

D’altra parte, anche se l’API Intersection Observer è supportata dalla maggior parte dei browser nelle versioni recenti, non è supportata proprio ovunque. Per fortuna esiste un polyfill pronto all’uso.

#3 Lozad.js, lazy loading in JavaScript

Un’alternativa rapida e comoda per implementare il lazy loading delle immagini è lasciare il lavoro pesante a una libreria JS.

Lozad è un lazy loader molto performante, leggero e configurabile, scritto in JavaScript puro e senza dipendenze. Puoi usarlo per caricare in lazy loading immagini, video, iframe e altro ancora, e si appoggia all’API Intersection Observer.

Puoi installare Lozad con npm o Yarn e importarlo con il module bundler che preferisci:

bash
npm install --save lozad

yarn add lozad
javascript
import lozad from 'lozad';

Oppure puoi scaricare la libreria da un CDN e aggiungerla in fondo alla pagina HTML in un tag < script>:

markup
<script src="https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js"></script>

Poi, per un’implementazione di base, aggiungi la classe lozad all’elemento nel tuo markup:

markup
<img class="lozad" data-src="img.jpg">

Infine istanzia Lozad nel tuo file JS:

javascript
const observer = lozad();
observer.observe();

Trovi tutti i dettagli sull’uso della libreria nel repository GitHub di Lozad.

Se non hai voglia di entrare negli ingranaggi dell’API Intersection Observer, o se cerchi solo un’implementazione rapida che copra vari tipi di contenuto, Lozad è un’ottima scelta.

Attenzione però al supporto dei browser: se serve, affianca alla libreria un polyfill per l’API Intersection Observer.

#4 Lazy loading con effetto sfocato

La prima cosa che vedi è una copia sfocata e a bassa risoluzione dell’immagine, mentre la versione ad alta risoluzione viene caricata in lazy loading:

Immagine segnaposto sfocata sul sito Medium
Immagine segnaposto sfocata sul sito Medium
Immagine ad alta risoluzione caricata in lazy loading sul sito Medium.
Immagine ad alta risoluzione, caricata in lazy loading, sul sito Medium.

Puoi caricare le immagini in lazy loading con questo effetto sfocato in diversi modi.

Ecco tutti i vantaggi di questa soluzione:

  • Prestazioni: appena 463 byte di CSS e 1.007 byte di JavaScript minificato.
  • Supporto degli schermi retina
  • Nessuna dipendenza: niente jQuery né altre librerie o framework.
  • Miglioramento progressivo per i browser più vecchi e per i casi in cui JavaScript non parte.

Per ottenere questo tipo di effetto puoi scaricare progressive-image.js.

#5 Yall.js, lazy loading in JavaScript

Yall è uno script di lazy loading ricco di funzionalità per immagini, video e iframe. Nello specifico usa l’API Intersection Observer e, quando serve, ripiega in modo intelligente sulle tecniche classiche di gestione degli eventi.

Quando includi Yall nel tuo documento devi inizializzarlo così:

javascript
<script src="yall.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", yall);
</script>

Poi, per caricare in lazy loading una semplice img, nel markup ti basta questo:

markup
<img class="lazy" src="placeholder.jpg" data-src="image-to-lazy-load.jpg" alt="Alternative text to describe image.">

Nota che:

  • aggiungi la classe Lazyload all’elemento
  • il valore di src è un’immagine segnaposto
  • il percorso dell’immagine da caricare in lazy loading sta nell’attributo data-src

Tra i vantaggi di Yall:

  • ottime prestazioni grazie all’API Intersection Observer
  • supporto dei browser eccellente (arriva fino a IE11)
  • nessuna dipendenza aggiuntiva

Per sapere che cosa offre Yall e per implementazioni più complesse, dai un’occhiata alla pagina su GitHub.

Conclusione

Ecco fatto: cinque metodi di lazy loading delle immagini da provare e testare nei tuoi progetti.

CSSHTML

Damien Flandrin Sviluppatore web dal 2010, creatore di Gekkode e di Email Impact. Ogni articolo è testato su un progetto reale prima della pubblicazione. Contatti
Newsletter

I nuovi test, tutorial e progetti, via e-mail.

Test riproducibili, codice versionato, risultati datati. Mai spam.