Il lazy loading (caricamento differito) è una delle tecniche di ottimizzazione più efficaci per migliorare le performance di una pagina web. Consiste nel ritardare il caricamento di risorse non immediatamente visibili (come immagini e iframe posizionati below-the-fold) fino a quando l’utente non si avvicina ad esse scorrendo la pagina. Con l’introduzione dell’attributo nativo loading in HTML, questa tecnica è diventata incredibilmente semplice da implementare, richiedendo un solo attributo senza alcun codice JavaScript.
Cos’è il Lazy Loading e Perché è Importante
Quando un browser carica una pagina web, per impostazione predefinita scarica tutte le risorse referenziate nel markup, incluse immagini che si trovano molto sotto la parte visibile dello schermo e che l’utente potrebbe non raggiungere mai. Questo comportamento, noto come eager loading, spreca banda, rallenta il caricamento iniziale della pagina e consuma risorse del dispositivo inutilmente.
Il lazy loading risolve questo problema caricando le risorse solo quando stanno per entrare nel viewport dell’utente. I benefici sono significativi e misurabili:
- Riduzione del tempo di caricamento iniziale: meno risorse da scaricare significa una pagina che diventa interattiva più rapidamente
- Risparmio di banda: gli utenti che non scorrono fino in fondo alla pagina non scaricano risorse che non vedranno mai
- Riduzione del carico sul server: meno richieste simultanee al caricamento della pagina distribuiscono il carico nel tempo
- Miglioramento dei Core Web Vitals: in particolare Largest Contentful Paint (LCP) e First Input Delay (FID) beneficiano della riduzione del lavoro iniziale
- Risparmio energetico: meno attività di rete e rendering significa minor consumo di batteria sui dispositivi mobili
Prima dell’attributo loading nativo, il lazy loading richiedeva librerie JavaScript dedicate o l’uso dell’Intersection Observer API. Queste soluzioni funzionano ancora e offrono maggiore controllo, ma l’attributo nativo ha il vantaggio della semplicità e della performance, poiché è gestito direttamente dal motore del browser.
L’Attributo loading=”lazy” per le Immagini
L’attributo loading può essere applicato al tag <img> e accetta tre valori: “lazy” per il caricamento differito, “eager” per il caricamento immediato (il comportamento predefinito), e “auto” che lascia al browser la decisione (attualmente equivalente a eager nella maggior parte dei browser).
L’implementazione è straordinariamente semplice: basta aggiungere loading=”lazy” al tag <img>. Il browser gestisce autonomamente tutto il meccanismo: monitora la posizione dell’immagine rispetto al viewport, inizia il download quando l’immagine si avvicina all’area visibile e la renderizza non appena il download è completato. Non serve alcun JavaScript aggiuntivo.
Il browser utilizza una soglia di distanza dal viewport per decidere quando iniziare il caricamento. Questa soglia varia tra browser e condizioni di rete: su connessioni veloci, il browser potrebbe iniziare a caricare l’immagine quando è a circa 1250 pixel dal viewport; su connessioni lente (come il 4G), la soglia aumenta a circa 2500 pixel per garantire che l’immagine sia pronta quando diventa visibile. Questo comportamento adattivo è uno dei vantaggi del lazy loading nativo rispetto alle soluzioni JavaScript.
È cruciale specificare sempre gli attributi width e height (o le dimensioni tramite CSS) sulle immagini con lazy loading. Senza dimensioni esplicite, il browser non può riservare lo spazio corretto nel layout prima che l’immagine venga caricata, causando il fenomeno del layout shift (CLS – Cumulative Layout Shift), che peggiora l’esperienza utente e i punteggi dei Core Web Vitals.
Lazy Loading per iframe
L’attributo loading=”lazy” funziona anche sul tag <iframe>, con un impatto potenzialmente ancora maggiore rispetto alle immagini. Gli iframe, specialmente quelli che incorporano video YouTube, mappe Google, widget social o contenuti di terze parti, possono essere molto pesanti: un singolo iframe di YouTube carica centinaia di kilobyte di JavaScript e CSS, anche se il video non viene mai riprodotto.
Applicando loading=”lazy” agli iframe below-the-fold, l’intero contenuto dell’iframe (inclusi tutti i suoi script, stili e risorse) viene differito fino a quando l’utente non si avvicina alla sua posizione nella pagina. In pagine con molti iframe (come gallerie video o pagine con mappe e widget social), questa ottimizzazione può ridurre il peso iniziale della pagina di svariati megabyte.
Per i video YouTube in particolare, combinare loading=”lazy” con la tecnica del facade pattern (mostrare un’immagine placeholder al posto dell’iframe e caricare l’iframe solo al clic dell’utente) offre il massimo risparmio di risorse. Per approfondire l’embedding di contenuti multimediali, consulta il nostro articolo su video e audio in HTML5.
Above-the-Fold: Quando NON Usare il Lazy Loading
Un errore comune e controproducente è applicare loading=”lazy” a tutte le immagini della pagina, incluse quelle visibili immediatamente al caricamento (above-the-fold). Le immagini nella parte superiore della pagina devono essere caricate il più velocemente possibile, poiché contribuiscono direttamente alla metrica Largest Contentful Paint (LCP), uno dei tre Core Web Vitals di Google.
Applicare lazy loading all’immagine LCP (quella più grande nella viewport iniziale) ritarda il suo caricamento invece di accelerarlo, poiché il browser deve prima attendere il completamento del layout per determinare la posizione dell’immagine e poi verificare che sia nel viewport prima di avviare il download. Senza lazy loading, il download inizierebbe immediatamente durante il parsing dell’HTML.
La regola pratica è: utilizzare loading=”eager” (o semplicemente omettere l’attributo loading) per le prime 1-3 immagini visibili al caricamento della pagina, e loading=”lazy” per tutte le altre. L’immagine hero, il logo del sito, le immagini di intestazione e qualsiasi contenuto visivo immediatamente visibile non devono avere lazy loading.
Per le immagini above-the-fold critiche, è consigliabile aggiungere l’attributo fetchpriority=”high” per segnalare al browser che il loro download ha priorità alta. Questo attributo funziona in sinergia con il lazy loading sulle altre immagini, creando una chiara gerarchia di priorità nel caricamento delle risorse.
Intersection Observer come Alternativa Avanzata
Per scenari che richiedono un controllo più fine del lazy loading, l’Intersection Observer API rimane la soluzione JavaScript più performante. Questa API permette di osservare quando un elemento entra o esce dal viewport (o da un elemento contenitore) e di eseguire azioni in risposta, senza l’overhead del polling o degli event listener su scroll.
I vantaggi di Intersection Observer rispetto all’attributo nativo includono: controllo preciso sulla soglia di attivazione (tramite il parametro threshold), possibilità di osservare margini personalizzati (rootMargin), callback personalizzata per qualsiasi azione (non solo il caricamento di immagini), e la possibilità di applicare lazy loading ad animazioni, caricamento di componenti, infinite scroll e qualsiasi altro contenuto dinamico.
Il pattern tipico con Intersection Observer per il lazy loading delle immagini prevede di inserire l’URL dell’immagine in un attributo data-src anziché in src, creare un observer che monitora tutte le immagini con lazy loading, e nel callback dell’observer copiare data-src in src quando l’immagine entra nel viewport. Dopo il caricamento, si chiama unobserve() per smettere di osservare l’immagine.
L’Attributo decoding e fetchpriority
Oltre a loading, HTML offre altri attributi per ottimizzare il caricamento delle immagini. L’attributo decoding controlla come il browser decodifica l’immagine: “async” permette al browser di continuare il rendering della pagina durante la decodifica dell’immagine, “sync” blocca il rendering fino al completamento della decodifica, e “auto” lascia la decisione al browser. Per la maggior parte delle immagini, decoding=”async” è la scelta ottimale.
L’attributo fetchpriority indica al browser la priorità relativa del download della risorsa: “high” per risorse critiche (immagine LCP), “low” per risorse meno importanti, e “auto” per la priorità predefinita. Combinare fetchpriority=”high” sull’immagine LCP con loading=”lazy” sulle immagini below-the-fold crea una strategia di caricamento ottimale che massimizza le performance percepite.
Per implementare una strategia di performance completa, è utile combinare il lazy loading con altre tecniche: dimensioni esplicite per prevenire layout shift, formati moderni come WebP e AVIF tramite il tag <picture>, srcset e sizes per immagini responsive, e preload per l’immagine LCP. Per approfondire il collegamento delle risorse e i meccanismi di preload, consulta la nostra guida su come collegare CSS e JavaScript.
Il lazy loading nativo rappresenta una delle vittorie più significative della piattaforma web in termini di performance: un singolo attributo HTML che può migliorare drasticamente i tempi di caricamento senza alcuna complessità aggiuntiva. Implementarlo correttamente, evitando di applicarlo alle risorse above-the-fold, è una delle ottimizzazioni con il miglior rapporto costo-beneficio nell’intero panorama dello sviluppo web.
Hai bisogno di aiuto con l’ottimizzazione delle performance del tuo sito web? G Tech Group offre servizi di sviluppo web professionale e consulenza sulla performance. Contattaci a su*****@********up.it o via WhatsApp al 0465 84 62 45.