Caricamento lento delle immagini

Le immagini possono essere visualizzate su una pagina web perché sono incorporate nel codice HTML come elementi <img> o immagini di sfondo CSS. In questo post scoprirai come eseguire il caricamento lento di entrambi i tipi di immagini.

Immagini incorporate

I candidati per il caricamento lento più comuni sono le immagini utilizzate negli elementi <img>. Con le immagini incorporate sono disponibili tre opzioni per il caricamento lento, che possono essere utilizzate in combinazione per ottenere la migliore compatibilità tra i browser:

Utilizzo del caricamento lento a livello di browser

Chrome e Firefox supportano entrambi il caricamento lento con l'attributo loading. Questo attributo può essere aggiunto a elementi <img> e anche a elementi <iframe>. Il valore lazy indica al browser di caricare immediatamente l'immagine se si trova nell'area visibile e di recuperare altre immagini quando l'utente scorre vicino a queste.

Consulta il campo loading della tabella di compatibilità del browser di MDN per dettagli sul supporto dei browser. Se il browser non supporta il caricamento lento, l'attributo verrà ignorato e le immagini verranno caricate immediatamente, come di consueto.

Per la maggior parte dei siti web, l'aggiunta di questo attributo alle immagini in linea incrementerà le prestazioni e permetterà agli utenti di caricare immagini che potrebbero non riuscire mai a scorrere. Se hai un numero elevato di immagini e vuoi assicurarti che gli utenti dei browser che non supportano il vantaggio del caricamento lento, dovrai combinarlo con uno dei metodi illustrati di seguito.

Per scoprire di più, consulta l'articolo Caricamento lento a livello di browser per il web.

Usare l'osservatore di intersezione

Per eseguire il polyfill del caricamento lento degli elementi <img>, utilizziamo JavaScript per verificare se si trovano nell'area visibile. In caso affermativo, gli attributi src (e talvolta srcset) vengono compilati con gli URL dei contenuti dell'immagine desiderati.

Se hai già scritto codice per il caricamento lento, potresti aver portato a termine l'attività utilizzando gestori di eventi come scroll o resize. Sebbene questo approccio sia il più compatibile tra i vari browser, i browser moderni offrono un modo più efficiente ed efficiente per controllare la visibilità degli elementi tramite l'API Intersection Observationr.

L'osservatore di intersezione è più facile da usare e da leggere rispetto al codice, perché si basa su vari gestori di eventi, in quanto è sufficiente registrare un osservatore per osservare gli elementi anziché scrivere noioso codice di rilevamento della visibilità degli elementi. Non ti resta che decidere cosa fare quando un elemento è visibile. Supponiamo che questo pattern di markup di base per gli elementi <img> caricati lentamente:

<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!">

Ci sono tre parti pertinenti di questo markup su cui dovresti concentrarti:

  1. L'attributo class, che corrisponde al nome con cui selezionerai l'elemento in JavaScript.
  2. L'attributo src, che fa riferimento a un'immagine segnaposto che verrà visualizzata al primo caricamento della pagina.
  3. Gli attributi data-src e data-srcset, che sono attributi segnaposto contenenti l'URL dell'immagine da caricare una volta che l'elemento sarà nell'area visibile.

Ora vediamo come utilizzare Intersection Observationr in JavaScript per eseguire il caricamento lento delle immagini con questo pattern di markup:

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
  }
});

Nell'evento DOMContentLoaded del documento, questo script esegue una query nel DOM per tutti gli elementi <img> con una classe lazy. Se l'osservatore intervista è disponibile, crea un nuovo osservatore che esegua un callback quando gli elementi img.lazy entrano nell'area visibile.

Intersection Observationr è disponibile in tutti i browser moderni. Di conseguenza, se utilizzi questo metodo come polyfill per loading="lazy", il caricamento lento sarà disponibile per la maggior parte dei visitatori.

Immagini in CSS

Sebbene i tag <img> siano il modo più comune di utilizzare le immagini sulle pagine web, le immagini possono essere richiamate anche tramite la proprietà CSS background-image (e altre proprietà). Il caricamento lento a livello di browser non si applica alle immagini di sfondo CSS, pertanto devi considerare altri metodi se hai immagini di sfondo per il caricamento lento.

A differenza degli elementi <img> che vengono caricati indipendentemente dalla loro visibilità, il comportamento di caricamento delle immagini in CSS avviene con maggiore speculazione. Quando vengono creati i modelli a oggetti del documento e CSS e l'albero di rendering, il browser esamina in che modo il CSS viene applicato a un documento prima di richiedere risorse esterne. Se il browser ha stabilito che una regola CSS che coinvolge una risorsa esterna non si applica al documento così come è attualmente creato, il browser non la richiede.

Questo comportamento speculativo può essere utilizzato per posticipare il caricamento delle immagini in CSS utilizzando JavaScript per determinare quando un elemento si trova all'interno dell'area visibile e, successivamente, applicando una classe all'elemento che applica lo stile richiamando un'immagine di sfondo. Questo fa sì che l'immagine venga scaricata al momento del bisogno anziché al caricamento iniziale. Ad esempio, prendiamo un elemento che contiene un'immagine di sfondo 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>

L'elemento div.lazy-background conterrebbe normalmente l'immagine di sfondo hero richiamata da alcuni CSS. In questo esempio di caricamento lento, tuttavia, puoi isolare la proprietà background-image dell'elemento div.lazy-background tramite una classe visible aggiunta all'elemento quando si trova nell'area visibile:

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

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

Da qui, utilizza JavaScript per verificare se l'elemento si trova nell'area visibile (con Intersection Observationr!), quindi aggiungi la classe visible all'elemento div.lazy-background in quel momento, che caricherà l'immagine:

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);
    });
  }
});

Effetti su Largest Contentful Paint (LCP)

Il caricamento lento è un'ottima ottimizzazione che riduce sia l'utilizzo complessivo dei dati che i conflitti di rete durante l'avvio rimandando il caricamento delle immagini a quando sono effettivamente necessarie. Ciò può migliorare i tempi di avvio e ridurre l'elaborazione nel thread principale riducendo il tempo necessario per la decodifica delle immagini.

Tuttavia, il caricamento lento è una tecnica che può influire negativamente sulla Largest Contentful Paint LCP del tuo sito web se ti va troppo di usare questa tecnica. Una cosa da evitare è il caricamento lento delle immagini che si trovano nell'area visibile durante l'avvio.

Quando utilizzi i caricatori lenti basati su JavaScript, è consigliabile evitare il caricamento lento delle immagini nell'area visibile perché queste soluzioni spesso utilizzano un attributo data-src o data-srcset come segnaposto per gli attributi src e srcset. Il problema qui è che il caricamento di queste immagini subirà un ritardo perché lo scanner di precaricamento del browser non riesce a trovarle durante l'avvio.

Anche l'utilizzo del caricamento lento a livello di browser per il caricamento lento di un'immagine nell'area visibile può tornare indietro. Quando il criterio loading="lazy" viene applicato a un'immagine nell'area visibile, l'immagine viene ritardata finché il browser non riconosce che si trova nell'area visibile, il che può influire sulla metrica LCP di una pagina.

Immagini con caricamento lento Mai visibili nell'area visibile durante l'avvio. È un pattern che influisce negativamente sulla metrica LCP del tuo sito e, di conseguenza, sull'esperienza utente. Se ti serve un'immagine all'avvio, caricala all'avvio il più velocemente possibile, evitando di farlo lentamente.

Librerie con caricamento lento

Se possibile, ti consigliamo di utilizzare il caricamento lento a livello di browser, ma se ti trovi in una situazione in cui non è possibile farlo, ad esempio un gruppo significativo di utenti continua a fare affidamento su browser meno recenti, puoi utilizzare le seguenti librerie per eseguire il caricamento lento delle immagini:

  • lazysizes è una libreria per il caricamento lento completa che esegue il caricamento lento di immagini e iframe. Il pattern utilizzato è abbastanza simile agli esempi di codice mostrati qui in quanto si associa automaticamente a una classe lazyload negli elementi <img> e richiede di specificare gli URL immagine negli attributi data-src e/o data-srcset, i cui contenuti vengono scambiati rispettivamente negli attributi src e/o srcset. Utilizza Intersection Observationr (che è possibile eseguire il polyfill) e può essere esteso con una serie di plug-in per eseguire operazioni come il caricamento lento. Scopri di più sull'uso della funzionalità lazysize.
  • vanilla-lazyload è un'opzione leggera per immagini con caricamento lento, immagini di sfondo, video, iframe e script. Sfrutta l'osservatore di intersezione, supporta le immagini adattabili e attiva il caricamento lento a livello di browser.
  • lozad.js è un'altra opzione Leggera che utilizza solo l'osservatore di intersezione. Di conseguenza, offre prestazioni elevate, ma dovrà essere usato per il polyfill prima di poter essere usato su browser meno recenti.
  • Se hai bisogno di una libreria di caricamento lento specifica di React, prendi in considerazione react-lazyload. Sebbene non utilizzi Intersection Observationr, offre un metodo familiare di caricamento lento delle immagini a coloro che sono abituati a sviluppare applicazioni con React.