Una stessa pagina viene vista su schermi larghi 360 pixel e su monitor da 2560, su telefoni con densità di pixel tripla e su vecchi portatili con densità standard. Se ogni visitatore riceve la stessa immagine, qualcuno viene penalizzato: chi è su smartphone scarica un file pensato per un monitor, con megabyte inutili su una rete mobile; chi ha uno schermo ad alta densità, se l’immagine è piccola, vede un risultato sfocato. La soluzione esiste da anni ed è supportata da tutti i browser: le immagini responsive, con gli attributi srcset e sizes.
Sono attributi semplici da scrivere e facili da sbagliare. Soprattutto sizes, che dice al browser quanto sarà grande l’immagine nella pagina, è spesso lasciato al valore predefinito o compilato in modo approssimativo, con il risultato che il browser scarica immagini molto più grandi del necessario. In questo articolo vediamo come funzionano, come il browser sceglie, quali sono gli errori più comuni, quando usare l’elemento picture e come gestire tutto questo in WordPress.
srcset: le varianti disponibili
L’attributo srcset elenca le versioni disponibili della stessa immagine, ciascuna con la propria larghezza reale in pixel, indicata con il suffisso w. Il browser non deve scaricarle per sapere quanto sono grandi: lo legge dall’attributo, e sceglie quale scaricare.
<img src="/media/scarpa-800.webp"
srcset="/media/scarpa-400.webp 400w,
/media/scarpa-800.webp 800w,
/media/scarpa-1200.webp 1200w,
/media/scarpa-1600.webp 1600w"
sizes="(min-width: 1024px) 400px, 100vw"
width="1600" height="1200" alt="Scarpa da trail running, vista laterale">
L’attributo src resta come riserva per i client che non conoscono srcset, e gli attributi width e height continuano a servire per riservare lo spazio e prevenire gli spostamenti del layout, come spiegato nell’articolo sul CLS: indicano le proporzioni, non la dimensione finale.
sizes: quanto sarà grande l’immagine
Per scegliere, il browser ha bisogno di sapere quanto spazio occuperà l’immagine nella pagina. Ma quando legge l’HTML, e comincia a scaricare le immagini, non ha ancora calcolato il layout: non sa se l’immagine occuperà tutta la larghezza, metà o un terzo. L’attributo sizes glielo dice in anticipo, con una serie di condizioni sulla larghezza dello schermo e la relativa dimensione. Nell’esempio: su schermi larghi almeno 1024 pixel l’immagine occupa 400 pixel; altrimenti occupa tutta la larghezza, 100vw.
Con questa informazione il calcolo è semplice: il browser prende la dimensione indicata da sizes, la moltiplica per la densità dello schermo, cioè quanti pixel fisici corrispondono a un pixel CSS, e sceglie la variante più piccola che copre il risultato.
Il browser ha una certa libertà in questa scelta: può preferire una variante già presente in cache anche se più grande, e in alcune condizioni può tener conto della qualità della connessione. Ma il principio è sempre lo stesso, e la qualità della scelta dipende interamente dalla correttezza di sizes.
L’errore più costoso
Il valore predefinito di sizes, quando manca, è 100vw: il browser presume che l’immagine occupi tutta la larghezza dello schermo. Per un’immagine di apertura a tutta pagina è corretto; per un’immagine in una griglia di prodotti a tre colonne, in una colonna laterale o in una miniatura, è sbagliato di tre, quattro, dieci volte. Il browser scarica varianti enormi per spazi piccoli, e il sito sembra ottimizzato, perché ha srcset, mentre non lo è.
Il valore corretto si ricava dal CSS della pagina: per ogni intervallo di larghezza dello schermo, quanto è larga l’immagine. Non serve una precisione assoluta: una stima per eccesso di poche decine di pixel è innocua, un errore di un ordine di grandezza no. La funzione calc() permette di esprimere larghezze che dipendono da margini e spaziature, per esempio calc((100vw - 64px) / 3) per tre colonne con margini laterali.
<!-- Griglia: 1 colonna su mobile, 2 su tablet, 3 su desktop con contenitore massimo di 1200px -->
sizes="(min-width: 1240px) 380px,
(min-width: 768px) calc((100vw - 64px) / 2),
calc(100vw - 32px)"
Quali varianti generare
Le varianti vanno scelte in funzione degli spazi reali del sito. Per un’immagine che può occupare da 360 a 1200 pixel CSS, su schermi con densità fino a 3, le dimensioni utili vanno da circa 400 a 2400 pixel reali. Un passo tra una variante e l’altra del 30-50 per cento è un buon compromesso: passi troppo piccoli moltiplicano i file senza benefici, passi troppo grandi costringono il browser a scaricare varianti molto più grandi del necessario.
Oltre una certa densità il guadagno visivo diventa difficile da percepire, mentre il peso continua a crescere. Molti siti, per questo, limitano la densità effettiva a 2, non generando varianti oltre il doppio della dimensione massima di visualizzazione: su uno schermo con densità 3 l’immagine resta perfettamente nitida per l’occhio, con un file sensibilmente più leggero.
I descrittori di densità
Per le immagini che hanno sempre la stessa dimensione, come un logo o un’icona, esiste una forma più semplice: invece delle larghezze, srcset elenca le varianti per densità, con il suffisso x, e non serve sizes.
<img src="/media/logo-200.png"
srcset="/media/logo-200.png 1x, /media/logo-400.png 2x"
width="200" height="60" alt="Logo dell’azienda">
Per loghi e icone, però, spesso la scelta migliore è il formato vettoriale SVG, che resta nitido a qualsiasi densità con un solo file leggero.
L’elemento picture: formati e direzione artistica
srcset e sizes offrono al browser versioni di dimensioni diverse della stessa immagine, e lasciano a lui la scelta. L’elemento picture serve quando la scelta deve seguire regole precise. Il primo caso è il formato: con più elementi source, ciascuno con il proprio tipo, il browser usa il primo formato che supporta, per esempio AVIF, poi WebP, poi JPEG, come abbiamo visto nell’articolo sui formati WebP e AVIF. Il secondo è la direzione artistica: su mobile si vuole un’immagine diversa, per esempio un taglio verticale del soggetto invece della panoramica usata su desktop.
<picture>
<!-- Taglio verticale su mobile -->
<source media="(max-width: 767px)"
srcset="/media/hero-verticale-600.avif 600w, /media/hero-verticale-900.avif 900w"
sizes="100vw" type="image/avif">
<!-- Panoramica su schermi più larghi -->
<source srcset="/media/hero-1200.avif 1200w, /media/hero-2000.avif 2000w"
sizes="100vw" type="image/avif">
<img src="/media/hero-1200.jpg" width="2000" height="900"
alt="Negozio in centro città al tramonto" fetchpriority="high">
</picture>
Con la direzione artistica le proporzioni cambiano tra le varianti, e per evitare spostamenti del layout anche gli elementi source possono indicare width e height, supportati dai browser moderni.
L’immagine LCP responsive
Per l’immagine principale della pagina, che spesso è l’elemento LCP, valgono le regole generali: nessun caricamento differito, fetchpriority="high", varianti nel formato moderno. Se l’immagine viene scoperta tardi, per esempio perché è uno sfondo definito nel CSS, un preload deve riportare le stesse varianti e la stessa regola di dimensione, con gli attributi imagesrcset e imagesizes, altrimenti il browser rischia di scaricare una variante e poi usarne un’altra, come spiegato nell’articolo su preload, preconnect e fetchpriority.
Come si comporta WordPress
WordPress genera automaticamente diverse dimensioni di ogni immagine caricata e, dalla versione 4.4, aggiunge srcset e sizes alle immagini dei contenuti. Le dimensioni generate dipendono da quelle registrate dal core e dal tema; i temi possono aggiungerne altre con add_image_size(). Il core riduce inoltre automaticamente le immagini caricate oltre una certa soglia di dimensione, conservando l’originale.
Il punto debole è proprio sizes. Il valore predefinito di WordPress presume che l’immagine sia larga quanto la sua dimensione registrata o quanto lo schermo, se più piccolo: corretto per le immagini nel corpo di un articolo, spesso sbagliato per griglie, colonne e schede di prodotto. Il filtro wp_calculate_image_sizes permette di correggerlo in base al contesto. Per le immagini caricate in modo differito, WordPress dalla versione 6.7 può usare il valore auto, che lascia al browser il calcolo della dimensione reale dopo il layout: una soluzione efficace per le immagini sotto la piega, supportata dai browser basati su Chromium.
// sizes corretto per le miniature della griglia prodotti del tema
add_filter(
'wp_calculate_image_sizes',
function ( $sizes, $size ) {
if ( 'tema-griglia' === $size ) {
return '(min-width: 1240px) 380px, (min-width: 768px) calc((100vw - 64px) / 2), calc(100vw - 32px)';
}
return $sizes;
},
10,
2
);
Come verificare
Il controllo più diretto si fa nel browser. Nei DevTools, selezionando un’immagine, la proprietà currentSrc indica quale variante è stata scelta, e il pannello mostra la dimensione con cui l’immagine viene visualizzata e quella del file. Se il file è largo il doppio o più dello spazio visualizzato moltiplicato per la densità dello schermo, sizes è probabilmente sbagliato. Conviene ripetere la verifica simulando schermi diversi, perché l’errore spesso riguarda solo alcuni intervalli di larghezza.
Lighthouse segnala le immagini sovradimensionate con un avviso dedicato, indicando il risparmio possibile. Nel pannello Network, ordinando per dimensione le immagini di una pagina di categoria o di un articolo con molte foto, si vede subito se il peso è ragionevole per ciò che l’utente vede. Le pagine con molte immagini, come i cataloghi dei negozi online visti nell’articolo sulle Core Web Vitals per WooCommerce, sono quelle dove l’errore costa di più.
Un esempio
Un negozio di arredamento ha pagine di categoria con 24 prodotti in una griglia a quattro colonne su desktop e a due colonne su mobile. Il tema registra una dimensione per le miniature di 800 pixel e lascia a WordPress il valore predefinito di sizes, che per quella dimensione indica fino a 800 pixel. Su uno smartphone largo 390 pixel, con densità 3, il browser presume che la miniatura occupi tutto lo schermo e cerca 1170 pixel reali, scaricando la variante più grande disponibile, mentre ogni miniatura occupa circa 180 pixel CSS, cioè 540 reali. Su desktop, dove ogni miniatura occupa circa 280 pixel e lo schermo ha densità 1, scarica di nuovo la variante da 800 pixel: quasi tre volte il necessario, per 24 immagini.
Con un filtro che descrive la griglia reale, 280 pixel su desktop e metà dello schermo meno i margini su mobile, e con una variante aggiuntiva da 300 pixel, la pagina di categoria da desktop passa da 2,1 megabyte di immagini a circa 700 kilobyte, e anche da mobile il peso si riduce sensibilmente. Nessuna immagine è meno nitida, perché ciascuna è scaricata esattamente alla risoluzione con cui viene mostrata. È il tipo di intervento che non si vede in un test della sola home page, e che su un catalogo con migliaia di prodotti e molte visite alle categorie fa una differenza sensibile sia per gli utenti sia per il traffico del server.
In sintesi
Le immagini responsive permettono a ogni visitatore di scaricare la variante adatta al proprio schermo. srcset elenca le varianti con la loro larghezza, sizes dice quanto sarà grande l’immagine nella pagina, e il browser moltiplica per la densità dello schermo e sceglie la più piccola che basta. L’elemento picture aggiunge il controllo sui formati e la possibilità di cambiare taglio a seconda dello schermo.
L’errore più frequente, e più costoso, è un sizes lasciato al valore predefinito per immagini che non occupano tutta la larghezza: il sito sembra ottimizzato, ma scarica file molte volte più grandi del necessario. Correggerlo in base al CSS reale, generare varianti adeguate agli spazi del sito e verificare nel browser quale variante viene scelta sono interventi semplici che, sulle pagine ricche di immagini, fanno risparmiare megabyte a ogni visita.