Indice dei contenuti dell'articolo:
Negli ultimi anni le metriche legate alla Web Performance sono diventate centrali per chi sviluppa o gestisce siti web. L’avvento dei Core Web Vitals, in particolare del parametro LCP (Largest Contentful Paint), ha portato a un cambiamento radicale nella modalità con cui gli sviluppatori ottimizzano le immagini nei loro progetti.
Eppure, in un ecosistema sempre più complesso come quello di WordPress, dove plugin e page builder intervengono pesantemente sul markup, ottenere un comportamento corretto del browser non è così scontato.
Uno dei casi più frequenti riguarda proprio Elementor, il celebre page builder visuale, e il modo in cui gestisce lazy load, preloading e priorità delle immagini. In questo articolo approfondiamo come funziona davvero il caricamento delle immagini in WordPress, perché spesso le immagini “hero” (quelle visibili sopra la piega, o above the fold) non vengono trattate come dovrebbero, e come risolvere in modo definitivo con un semplice fix PHP.
Il problema di base: come WordPress gestisce le immagini
A partire da WordPress 5.5, il core ha introdotto automaticamente l’attributo loading="lazy"
su tutte le immagini inserite nei contenuti.
Questo comportamento ha un obiettivo chiaro: ridurre il tempo di caricamento iniziale evitando di scaricare risorse non visibili all’utente al primo rendering.
In pratica, se un’immagine si trova sotto la piega (below the fold), viene caricata solo quando il visitatore scorre la pagina. È una soluzione intelligente per ridurre il peso complessivo della pagina, ma ha un effetto collaterale importante:
anche l’immagine principale — quella che spesso rappresenta il contenuto più grande e visibile appena si apre la pagina — rischia di essere caricata in ritardo, penalizzando la metrica LCP.
Il browser infatti non distingue a priori quale immagine sia più importante, e applica il lazy load indiscriminatamente.
WordPress fa del suo meglio per gestire automaticamente alcune eccezioni, ma quando intervengono page builder come Elementor, il markup cambia, e i meccanismi di rilevamento standard non funzionano più come previsto.
L’interferenza del lazy load di Elementor
Elementor applica spesso il proprio sistema di lazy loading sulle immagini, sovrapponendosi a quello di WordPress.
In molte installazioni, l’attributo loading="lazy"
viene aggiunto direttamente dai widget immagine o galleria, oppure ereditato da plugin di ottimizzazione come NitroPack, WP Rocket o LiteSpeed Cache.
Il risultato?
Le immagini “hero” — cioè quelle posizionate above the fold — vengono comunque caricate tardi, perché marcate come “lazy”.
Google PageSpeed Insights o Lighthouse, analizzando la pagina, restituiscono spesso messaggi come:
In sostanza, l’immagine principale non viene considerata “prioritaria” dal browser, e questo peggiora la percezione visiva del caricamento, anche se il server e la rete sono rapidissimi.
Capire l’above the fold e il ruolo dell’immagine LCP
Il termine above the fold (in italiano sopra la piega) deriva dal mondo della carta stampata: nei giornali, tutto ciò che si trovava nella metà superiore della prima pagina — quella visibile anche quando il giornale era piegato — era considerato il contenuto più importante.
Nel web design e nello sviluppo front-end il concetto è rimasto lo stesso: l’above the fold è la parte della pagina visibile all’utente senza bisogno di scrollare, cioè quella che appare immediatamente quando si apre il sito.
Questa porzione ha un ruolo fondamentale, perché rappresenta il primo impatto visivo con l’utente.
È qui che si forma l’opinione iniziale su velocità, affidabilità e qualità del sito.
Se l’area above the fold si carica lentamente, l’utente percepisce il sito come “pesante” o “lento”, anche se il resto della pagina si comporta in modo impeccabile.
Per questo motivo, tutti gli elementi presenti sopra la piega dovrebbero caricarsi nel minor tempo possibile: immagini hero, loghi, testi principali, call-to-action e sfondi del primo blocco.
Non è solo una questione estetica, ma di esperienza utente e di conversione: più l’utente vede rapidamente il contenuto, più è probabile che resti sul sito e interagisca.
Google misura proprio questa percezione attraverso una delle sue metriche chiave dei Core Web Vitals, chiamata LCP (Largest Contentful Paint).
Questa metrica valuta quanto tempo impiega l’elemento visivamente più grande — che solitamente è un’immagine hero, un banner, o un grande blocco di testo — a comparire completamente sullo schermo.
Un LCP buono è quello che avviene entro 2,5 secondi dal momento in cui la pagina inizia a caricarsi.
Sopra questa soglia, l’esperienza è percepita come lenta, e i punteggi di PageSpeed e Core Web Vitals ne risentono.
Il problema è che, se l’immagine principale viene caricata con loading="lazy"
(cioè in modalità “pigra”) o senza una priorità di rete adeguata, il browser la scaricherà solo dopo aver completato il parsing dell’intero documento HTML.
In altre parole, il file dell’immagine arriva troppo tardi rispetto a quando il browser potrebbe già mostrarla, causando un ritardo visibile nella comparsa del contenuto principale.
Questo significa che, anche su server veloci, CDN ottimizzati e siti ben configurati, l’esperienza percepita dall’utente può risultare lenta solo per via di un attributo HTML errato o per la mancanza di una priorità di caricamento adeguata.
È per questo che oggi strumenti come il fetchpriority="high"
e i tag di preloading sono diventati cruciali: servono a comunicare esplicitamente al browser quali risorse meritano la precedenza assoluta, cioè quelle che compaiono above the fold e che definiscono la prima impressione del sito.
L’importanza del preloading
Per evitare questi ritardi, si può dire al browser di precaricare risorse critiche attraverso l’elemento HTML <link rel="preload">
.
Un preload forza il browser a scaricare la risorsa (immagine, font, video, CSS o JS) appena scoperta nel documento, anche se non è ancora necessaria al rendering.
Esempio classico per un’immagine hero:
<link rel="preload" as="image" href="https://example.com/hero.jpg" fetchpriority="high">
Questo approccio garantisce che l’immagine sia già disponibile in cache quando il browser la incontra nel markup <img>
.
Tuttavia, non è sempre la soluzione più pratica in WordPress, perché:
- aggiungere preload dinamici richiede codice custom;
- se un CDN o un plugin riscrive le URL, si rischia di precaricare un file diverso;
- e soprattutto, se il page builder cambia l’ordine del DOM, il preload può perdere efficacia.
L’attributo fetchpriority: la scorciatoia moderna
Nel 2022 i principali browser (Chrome, Edge, Safari) hanno introdotto un nuovo attributo nativo:
fetchpriority="high"
A differenza del preload, che forza il download anticipato, fetchpriority
non cambia il momento in cui la risorsa viene richiesta, ma influenza la priorità della connessione durante il caricamento.
È una direttiva più “leggera” e più sicura da gestire:
il browser decide comunque quando scaricare l’immagine, ma se trova fetchpriority="high"
su un’immagine “above the fold”, la metterà in coda prima delle altre.
Esempio:
<img src="hero.webp" loading="eager" fetchpriority="high" decoding="async" alt="Hero image">
L’uso combinato di loading="eager"
(scarica subito) e fetchpriority="high"
(alta priorità di rete) è oggi il modo più efficace per garantire un LCP veloce, anche senza preload manuale.
Elementor e il problema del controllo sul markup
In teoria, sarebbe sufficiente impostare gli attributi corretti sugli <img>
che compaiono in hero section o in slider above the fold.
Ma Elementor, come molti builder visuali, non espone direttamente questi attributi nei campi del widget.
Ogni immagine inserita in una sezione o colonna Elementor è in realtà racchiusa in più livelli di <div>
, wrapper, overlay, lazy loader o animazioni.
Di conseguenza:
- il browser non trova l’immagine nel documento iniziale (perché è nascosta o caricata via JS),
fetchpriority="high"
non può essere aggiunto manualmente,- e
loading="lazy"
resta attivo anche dove non dovrebbe.
Questo comportamento è stato segnalato da molti utenti, ma fino ad oggi Elementor non ha introdotto un’opzione nativa per escludere facilmente un’immagine dal lazy load o per assegnarle una priorità alta.
Il contesto reale: immagini LCP in Elementor
Facciamo un esempio concreto.
Immagina di avere un blocco “Hero” in Elementor, con una grande immagine di sfondo o un’immagine dentro una colonna come elemento visivo principale.
Il markup risultante potrebbe assomigliare a questo:
<div class="elementor-element elementor-element-123 heroimage"> <img decoding="async" loading="lazy" src="https://example.com/wp-content/uploads/hero.jpg" alt="Hero section"> </div>
Google PageSpeed ti segnalerà che:
- il caricamento lento (
loading="lazy"
) non è appropriato per l’immagine LCP, - e che devi applicare
fetchpriority="high"
.
Ma Elementor non ti consente di modificare questi attributi dall’interfaccia, e WordPress continua a marcarla come “lazy” per impostazione predefinita.
Da qui nasce la necessità di intervenire a valle, cioè dopo che la pagina è stata generata, per correggere il markup.
Above the fold e priorità visiva
Non tutte le immagini della pagina meritano la stessa priorità.
L’unico criterio sensato è la posizione visiva: le immagini above the fold vanno scaricate subito, le altre no.
Il problema è che Elementor non distingue fra i due casi. Tutte le immagini vengono trattate allo stesso modo, e anche un’hero image finisce con loading="lazy"
.
Questo significa che l’utente vedrà magari la navbar e un po’ di testo, ma non l’immagine principale per uno o due secondi, anche su connessioni veloci.
A livello tecnico, il browser si trova a scaricare prima risorse secondarie (icone, immagini di sfondo, media nascosti nei tab) e solo dopo l’immagine più grande della pagina.
L’effetto visivo è un “flash” bianco o un layout che si completa tardi, penalizzando l’esperienza utente e i Core Web Vitals.
La soluzione ideale: un fix lato output buffer
Una soluzione elegante è intercettare l’output HTML generato da Elementor e correggerlo prima che venga inviato al browser.
Questo approccio ha diversi vantaggi:
- non richiede modifiche ai widget o ai template;
- non altera il funzionamento di Elementor;
- si applica solo in frontend (non nell’editor).
In pratica, possiamo utilizzare l’output buffering di PHP (ob_start()
) per catturare l’HTML generato dalla pagina, cercare le immagini che si trovano dentro una sezione con una classe specifica (ad esempio .heroimage
), e applicare in modo automatico gli attributi corretti.
Il nostro fix per Elementor
Per risolvere in modo definitivo il problema di lazy load e fetchpriority sulle immagini principali, condividiamo qui sotto un fix open source che può essere inserito nel file functions.php
del tema o, meglio ancora, in un piccolo mu-plugin personalizzato.
add_action('template_redirect', function () { if (is_admin() || wp_doing_ajax()) return; // Escludi le richieste AJAX di Elementor if (isset($_REQUEST['action']) && strpos($_REQUEST['action'], 'elementor') !== false) { return; } ob_start('elementor_add_fetchpriority_to_target_images'); }); function elementor_add_fetchpriority_to_target_images($html) { // Trova tutti i div con classe heroimage e le loro img $pattern = '/<div[^>]*class="[^"]*heroimage[^"]*"[^>]*>.*?<img([^>]*)>/is'; $html = preg_replace_callback($pattern, function ($matches) { $img_tag = $matches[0]; // Aggiungi fetchpriority="high" se non presente if (strpos($img_tag, 'fetchpriority=') === false) { $img_tag = preg_replace('/<img/', '<img fetchpriority="high"', $img_tag); } // Rimuovi loading="lazy" $img_tag = preg_replace('/\s*loading=(["\'])lazy\1/', '', $img_tag); return $img_tag; }, $html); return $html; }
Come funziona
- Hook
template_redirect
Il codice entra in azione solo sul frontend del sito, dopo che WordPress ha caricato il template ma prima di inviare l’HTML al browser. - Output buffering (
ob_start
)
Cattura l’output completo della pagina generata da Elementor. - Regex su classi “heroimage”
Cerca tutti i<div>
che contengono la classeheroimage
e individuano la relativa<img>
al loro interno. - Correzione del markup
- Rimuove eventuali
loading="lazy"
. - Aggiunge
fetchpriority="high"
se non presente.
In questo modo, l’immagine principale viene trattata come prioritaria, anche se Elementor o WordPress continuano a forzare il lazy load.
- Rimuove eventuali
- Restituzione dell’output corretto
L’HTML modificato viene restituito al browser, garantendo che le immagini principali siano scaricate immediatamente.
Perché è un approccio intelligente
Questo fix non va a interferire con il normale funzionamento di Elementor, né con i plugin di ottimizzazione come NitroPack, WP Rocket o LiteSpeed Cache.
Funziona solo in fase di output e solo per gli elementi che hanno esplicitamente una classe .heroimage
.
In questo modo puoi decidere tu, direttamente dal builder, quali sezioni devono contenere immagini prioritarie.
È sufficiente aggiungere la classe heroimage
alla sezione o al contenitore principale dell’hero, e lo script farà tutto da solo.
Integrazione con i plugin di caching
Poiché il fix agisce sull’output HTML finale, funziona perfettamente anche in presenza di sistemi di caching lato server o plugin di ottimizzazione.
Una volta che il buffer viene modificato la prima volta, la versione ottimizzata viene memorizzata nella cache, quindi il costo computazionale è nullo nelle richieste successive.
È consigliabile svuotare la cache dopo l’attivazione, per garantire che le pagine vengano rigenerate con i nuovi attributi.
Risultato su PageSpeed Insights
Dopo aver applicato questo fix, la differenza nei report di Google PageSpeed Insights o Lighthouse è immediata:
- La voce “Deve essere applicata fetchpriority=high” scompare.
- L’immagine hero viene segnalata come “rilevabile nel documento iniziale”.
- La metrica LCP migliora in modo netto, spesso con un guadagno di 80–100 ms sul tempo totale di rendering percepito.
Estensioni possibili
Chi desidera un controllo più granulare può estendere lo script in vari modi:
- Applicare il fix solo su determinati template o tipi di post.
- Aggiungere anche
loading="eager"
odecoding="async"
oltre alfetchpriority="high"
. - Gestire più classi CSS (ad esempio
.hero
,.banner
,.featured
).
Ecco un esempio di variante che include loading="eager"
:
<?php if (strpos($img_tag, 'loading=') === false) { $img_tag = preg_replace('/<img/', '<img loading="eager"', $img_tag); } ?>
Conclusioni
Il caricamento efficiente delle immagini è uno degli aspetti più importanti per garantire prestazioni elevate e punteggi Core Web Vitals ottimali.
In WordPress, e in particolare con Elementor, il comportamento di default può però ostacolare il raggiungimento di questi obiettivi, a causa del lazy load applicato in modo indiscriminato.
Intervenendo direttamente sull’output HTML e correggendo le immagini principali con fetchpriority="high"
, è possibile ripristinare il comportamento ideale del browser:
scaricare prima le risorse più importanti, rendendo l’esperienza utente fluida e visivamente immediata.
Il fix proposto è semplice, efficace e completamente compatibile con ogni ambiente hosting.
Basta aggiungere una classe CSS (heroimage
) alle sezioni above the fold e lasciare che lo script si occupi del resto.
Un piccolo intervento tecnico, ma con un grande impatto sui tempi di caricamento percepiti e sul punteggio LCP.