Caricamento lento delle immagini

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

Immagini in linea

I candidati al caricamento lento più comuni sono le immagini utilizzate negli elementi <img>. Con le immagini in linea 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 il caricamento lento con l'attributo loading. Questo attributo può essere aggiunto agli elementi <img> e anche agli 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 nelle vicinanze.

Per informazioni dettagliate sul supporto dei browser, consulta il campo loading della tabella sulla compatibilità del browser di MDN. 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 comporterà un miglioramento delle prestazioni e consentirà agli utenti di salvare immagini che potrebbero non visualizzare mai. Se hai un numero elevato di immagini e vuoi assicurarti che gli utenti di browser che non supportano il caricamento lento, dovrai combinare questa operazione con uno dei metodi spiegati di seguito.

Per scoprire di più, consulta la pagina relativa al caricamento lento a livello di browser per il web.

Utilizzo di Intersection Observer

Per eseguire il polyfill del caricamento lento degli elementi <img>, utilizziamo JavaScript per verificare se si trovano nell'area visibile. Se lo sono, gli attributi src (e talvolta srcset) vengono completati con gli URL relativi ai contenuti dell'immagine desiderati.

Se hai già scritto codice per il caricamento lento, potresti aver completato la tua attività utilizzando gestori di eventi come scroll o resize. Sebbene questo approccio sia il più compatibile con tutti i browser, quelli moderni offrono un modo più efficace ed efficiente per controllare la visibilità degli elementi tramite l'API Intersection Observer.

L'osservatore di intersezione è più facile da usare e leggere rispetto al codice che si basa su vari gestori di eventi, perché è sufficiente registrare un osservatore per osservare gli elementi anziché scrivere un noioso codice di rilevamento della visibilità degli elementi. Devi solo 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 è lo strumento con cui selezionerai l'elemento in JavaScript.
  2. 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 che caricherai una volta che l'elemento sarà nell'area visibile.

Ora vediamo come usare Intersection Observer in JavaScript per eseguire il caricamento lento delle immagini utilizzando 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 di intersezione è disponibile, crea un nuovo osservatore che esegue un callback quando gli elementi img.lazy entrano nell'area visualizzatore.

Intersection Observer è disponibile in tutti i browser moderni. Pertanto, l'utilizzo come polyfill per loading="lazy" garantirà la disponibilità del caricamento lento per la maggior parte dei visitatori.

Immagini in CSS

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

A differenza degli elementi <img>, che si caricano indipendentemente dalla loro visibilità, il comportamento di caricamento delle immagini in CSS prevede più speculazioni. Quando vengono creati i modelli di documenti e oggetti CSS e l'albero di rendering, il browser esamina il modo in cui CSS viene applicato a un documento prima di richiedere risorse esterne. Se il browser ha determinato che una regola CSS che coinvolge una risorsa esterna non si applica al documento in quanto è attualmente costruito, il browser non la richiede.

Questo comportamento speculativo può essere utilizzato per rinviare il caricamento delle immagini in CSS utilizzando JavaScript per determinare quando un elemento si trova all'interno dell'area visibile e applicando successivamente all'elemento una classe per applicare lo stile richiamando un'immagine di sfondo. Questo fa sì che l'immagine venga scaricata al momento necessario e non durante il caricamento iniziale. Ad esempio, prendiamo un elemento che contiene un'immagine di sfondo hero di grandi dimensioni:

<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 di solito contiene 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 Observer!) e aggiungi in quel momento la classe visible all'elemento div.lazy-background, che carica 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 sulla visualizzazione più grande con contenuti (LCP)

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

Tuttavia, il caricamento lento è una tecnica che può influire negativamente sul Largest Contentful Paint LCP del tuo sito web se non ti piace questa tecnica. È consigliabile evitare il caricamento lento delle immagini che si trovano nell'area visibile durante l'avvio.

Quando utilizzi programmi di caricamento lento basati su JavaScript, conviene 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 verrà ritardato 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 a essere presente. Quando loading="lazy" viene applicato a un'immagine nell'area visibile, l'immagine viene ritardata finché il browser non sa con certezza che si trova nell'area visibile, il che può influire sull'LCP di una pagina.

Non utilizzare mai il caricamento lento delle immagini visibili nell'area visibile durante l'avvio. Si tratta di un pattern che influisce negativamente sull'LCP del tuo sito e, di conseguenza, sull'esperienza utente. Se hai bisogno di un'immagine all'avvio, caricala il più rapidamente possibile evitando il caricamento lento.

Caricamento lento delle librerie

Se possibile, dovresti 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 che dipendono ancora da browser meno recenti, puoi utilizzare le seguenti librerie per il caricamento lento delle immagini:

  • lazysizes è una libreria per il caricamento lento completo, che esegue il caricamento lento di immagini e iframe. Il pattern utilizzato è molto simile a quello degli esempi di codice mostrati qui, in quanto si associa automaticamente a una classe lazyload sugli elementi <img> e richiede di specificare gli URL immagine negli attributi data-src e/o data-srcset, i cui contenuti vengono scambiati in attributi src e/o srcset, rispettivamente. Utilizza Intersection Observer (che puoi usare con il polyfill) e può essere esteso con diversi plug-in per fare cose come il caricamento lento di video. Scopri di più sull'uso delle dimensioni lazy.
  • vanilla-lazyload è un'opzione leggera per il caricamento lento di immagini, immagini di sfondo, video, iframe e script. Sfrutta Intersection Observer, supporta immagini reattive e abilita il caricamento lento a livello di browser.
  • lozad.js è un'altra opzione leggera che utilizza solo Intersection Observer. Di conseguenza, ha prestazioni elevate, ma dovrà essere sottoposto a polyfill prima di poter essere usato su browser meno recenti.
  • Se hai bisogno di una libreria per il caricamento lento specifico di React, prendi in considerazione react-lazyload. Sebbene non utilizzi Intersection Observer, offre un metodo familiare di caricamento lento delle immagini per coloro che sono abituati a sviluppare applicazioni con React.