Immagini responsive. Ora.

La proliferazione di un numero sempre maggiore di dispositivi con risoluzioni e tecnologie di visualizzazione diverse ha introdotto sfide e possibilità interessanti nel panorama del design digitale.

Riportando una frase celebre, “da grandi poteri derivano grandi responsabilità”, i poteri indotti dalla capacità di sfruttare ogni singolo pixel su schermo ci permettono di archiviare un design d’espressione superiore, ma ad un costo.

La controparte di una qualità maggiore è il peso del file che la contiene. Più pixel o maggiore densità, maggiore il peso. Sebbene il Responsive Web Design abbia effettivamente migliorato l’esperienza d’uso servendo soluzioni dedicate, in molte circostanze un normale sito web continua(va) a scaricare le stesse risorse (=immagini) in ogni occasione, indipendentemente dalle specifiche del dispositivo. Così su dispositivi non Retina vengono visualizzate immagini con doppia densità di pixel (2x), chiaramente più pesanti rispetto alla qualità 1x. Uno spreco di risorse non indifferente, considerando che le immagini costituiscono il 64% della grandezza media di una pagina web.

Contenuto medio in byte di una pagina

Contenuto medio in byte di una pagina

In che misura stiamo prendendoci la responsabilità di esperienze utente degradate dell’eccessivo response time delle risorse caricate?

Non c’è più ragione di indugiare in compromessi. Il supporto nativo alle immagini responsive ora c’è.

In questo articolo vedremo come implementare questa tecnica e iniziare a fornire una migliore esperienza utente ai navigatori del nostro sito.

Prima di iniziare, un paio di domande

Chiediti cosa vorresti dare ai tuoi utenti e in che modo, basandoti sulle attuali specifiche del tuo design:

  1. Nel tuo sito, vorresti che le immagini si ridimensionassero in base alla viewport?
  2. Vorresti fornire immagini ottimizzate per schermi con alta densità di pixel (HDPI screen)?
  3. Vorresti sfruttare alcuni dei nuovi formati web disponibili, fornendo mime type diversi?
  4. Vorresti usare la tecnica della “Art Direction” per fornire specifiche esperienze d’uso? (Maggiori spiegazioni sul termine più avanti)

Approfondiremo ciascuno di questi punti con soluzioni specifiche per ogni esigenza di design, anche con combinazione delle stesse.

Immagini a width fissa e variabile ottimizzate per densità pixel

Fixed width

Supponiamo che il tuo sito non sia responsive. Le immagini avranno una width fissa a prescindere dal dispositivo che le visualizza. È comunque possibile usare immagini responsive fornendo versioni diverse delle stesse a seconda della densità dei pixel dello schermo (forniremo immagini ottimizzate per schermi HDPI). Useremo l’attributo <srcset> dell’elemento <img>:

<img src="img_500px.jpg" srcset="img_750px.jpg 1.5x, img_1000px.jpg 2x" width="500">

La source della nostra immagine specifica una width a 500px per schermi a densità 1. Notare che questa è la scelta di default e la specifichiamo nella source per massimizzare la compatibilità con browsers che non supportano <srcset>. Se il browser non la riconosce, guarderà per la source predefinita. Se lo schermo ha densità pixels 1.5, forniremo al browser un’immagine con width 750px; se 2x, 1000px.

Variable width: il problema

Il tuo sito è responsive e le immagini si adattano alla grandezza dello schermo del device che le visualizza. Tuttavia, a differenza di prima, si introduce un livello di complessità. Su schermi con stessa densità di pixel ma con risoluzioni diverse, viene fornita la stessa immagine. Su uno smartphone con risoluzione a 480px verrà visualizzata la stessa immagine che su uno schermo Full HD a 1920px e ciò significherà interpolazione e perdita di qualità. La soluzione migliore sarebbe fornire un’immagine specifica basata sulla viewport del device. Ma c’è un problema: il browser non conosce a priori la grandezza, in quanto essa risulta dal rendering CSS e dalla disposizione degli elementi, che a loro volta possono dipendere dalla grandezza delle immagini. Come usciamo dal loop?

La soluzione: media queries for the win!

Possiamo comunque fare una stima in base all’estensione dell’immagine, perché è il nostro design. Leggasi, sappiamo orientativamente quanto spazio riserviamo a ciascuna immagine nel layout e quale relazione intercorre tra gli elementi in termini di grandezza.

Andremo a settare dei breakpoint utilizzando le media query CSS nell’attributo <sizes> dell’elemento <img>. Media query negli attributi? Fa’ un respiro profondo e proseguiamo (prometto che ne varrà la pena).

<img sizes="(max-width: 30em) 100vw,
			(max-width: 50em) 50vw, calc(33vw - 100px)"
	srcset="img-200.jpg 200w,
			img-400.jpg 400w, img-800.jpg 800w, img-1600.jpg 1600w"
	src="img-400.jpg">

Con ordine. L’attributo <srcset> contiene una lista di immagini che il browser può scegliere. Il descrittore “w” nel <srcset> descrive la width del file (attenzione, non della viewport): il browser ha quindi a disposizione 4 immagini. Ma c’è un errore, non si era detto che il browser non conosce l’effettiva grandezza dell’immagine? Che senso ha settare un breakpoint? Giustissimo. L’attributo <sizes> entra in gioco proprio ora.
Come puoi vedere, c’è una coppia di valori.

1. max-width: 30em     2. 100vw

Il primo valore corrisponde a una query CSS (questo valore è opzionale); il secondo, ad una grandezza. Cosa succede? Il browser scorrerà le varie media queries (il primo valore della coppia), per trovare quella che corrisponde all’attuale ed effettiva grandezza della viewport. Una volta riscontrata, il browser applica il secondo valore della coppia come grandezza dell’immagine, o meglio fornisce una stima della stessa (ricordiamo che la grandezza effettiva dell’immagine dipende dal rendering finale).

Facciamo un esempio per chiarire il tutto. Supponiamo che la grandezza del font nel nostro sito è 16px e che la viewport abbia una grandezza di 20 em (corrisponde cioè a 320px). Il browser scorrerà la lista di coppie nel <sizes>: in questo caso si fermerà alla prima, perché abbiamo settato un breakpoint a 30em (la nostra viewport ne ha 20). La grandezza corrispondente è di 100vw, quindi la totalità dello schermo (assumendo che la densità di pixel sia pari ad 1), così l’immagine sarà grande 320px o più. Il browser sceglierà quindi img-400.jpg, poiché la prima maggiore di 320px nella lista in <srcset>.

Art Direction

Questo termine, applicato alle immagini responsive, indica il metodo secondo cui serviamo specifiche aree dell’immagine in base al breakpoint del layout. Questo metodo viene usato per consentire agli utenti di vedere la porzione di immagine che noi designer vogliamo loro mostrare (un’area specifica, ad esempio). Questo risultato è ottenuto con l’uso degli elementi <picture>, <source> e <img>. Vediamo come.

<picture>
	<source media="(min-width: 45em)" srcset="large.jpg">
	<source  media="(min-width:  32em)" srcset="med.jpg">
	<img src="small.jpg">
</picture>

Ancora una volta, abbiamo a disposizione una lista di immagini accompagnate da query CSS. Una source per ciascun breakpoint, corrispondente ad altrettante immagini. Se nessuno dei breakpoint è raggiunto, viene usata una sorta di fallback fornita dall’<img>, grazie alla quale abbiamo sempre una scelta di default. È comunque l’elemento <img> a svolgere gran parte del lavoro: esso si serve dei gemelli per consentire la scelta al browser, ma, in caso di non matching, verrà mostrata l’immagine specificata nel suo attributo e <src>.

Formati Diversi (mime types)

Il dominio del formato lightweight .PNG e la sorellastra .JPG sul web come standard de facto per l’implementazione di immagini dall’alta qualità e dal peso contenuto, sembra destinato a indebolirsi con l’introduzione di due nuovi formati progettati per archiviare qualità e prestazioni maggiori in grandezze più piccole sino al 34%.

WebP (image/webp): creazione di Google, nasce come sostituto più leggero della sorella .PNG. Questo formato incorpora algoritmi di compressione lossy e lossless, risulta più leggero del formato PNG del 26% e fino al 34% del formato JPEG. Supporta la trasparenza risultando ugualmente sino a 3 volte più piccolo.

responsive02

Attualmente questo formato è supportato da Chrome, Opera e Android Browser. Non molto, in realtà.

Perché usarlo se ha un supporto limitato? Fornire un’esperienza che sfrutta tecnologie di browser specifici non è in generale una buona idea, a meno che non si disponga di fallback per i browser non supportati e l’esperienza non risulti troppo degradata. In questo caso, tuttavia, usare una tecnologia specifica non comporta rischi particolari: nel caso in cui il browser supporti il formato, avremo un guadagno in prestazioni e qualità sino al 34%; nel caso in cui il browser non lo supporti, forniremo comunque un’immagine in un formato nato per le prestazioni sul web.
Possiamo integrarlo con questo codice:

<picture>
	<source type="image/webp" srcset="img.webp">
	<img src="img.png" alt="An image.">
</picture>

Jpeg XR: nasce come evoluzione dell’antecedente .JPEG, sulla quale può avere il doppio dell’efficienza di compressione con minor perdita di qualità visiva, con algoritmi lossy e lossless.

responsive03

Il supporto a questo formato è ancora minore del precedente: solo IE ed Edge supportano questo standard (è infatti sviluppato da Microsoft).

Per implementarlo nel codice:

<picture>
	<source type="image/vnd.ms-photo" srcset="image.jpxr">
	<img src="image.jpg" alt="The same image.">
</picture>

Ma l’unione fa la forza! Combinando i due formati avremo rapporti di efficienza maggiori: per Firefox e Safari, almeno per il momento, ricorreremo a una fallback tradizionale come visto negli esempi precedenti.

<picture>
	<source type="image/webp" srcset="image.webp">
	<source type="image/vnd.ms-photo" srcset="image.jpxr"> 
	<img src="image.jpg" alt="Same image as before.">
</picture>

BPG è il terzo e più recente formato introdotto per rimpiazzare JPG, con minore grandezza e maggiore qualità grafica. Sebbene i vantaggi di questo nuovo formato siano molteplici, ancora non è stato possibile fare test estensivi di compatibilità per includerlo in questo articolo.

Putting all together

Riepiloghiamo rapidamente le soluzioni viste.

Per un design non responsive è possibile fornire immagini diverse a seconda della densità dei pixel dello schermo che le visualizza. In questo modo, forniamo immagini di qualità superiore solo ai device che supportano tecnologie specifiche e immagini SD altrimenti.

Per un design responsive, mediante le media query CSS, possiamo fornire al browser suggerimenti per scegliere immagini proporzionate alla viewport. In questo modo, su schermi più piccoli forniremo immagini più leggere e con minor risoluzione, eviteremo l’interpolazione ed assicureremo qualità specifiche al device.

Per adaptive design, mediante Art Direction, l’utente visualizzerà specifiche aree e porzioni dell’immagine, così che, mediante l’implementazione dell’elemento, assicureremo fluidità ed esperienze personalizzate. Singolarmente, queste soluzioni sono in grado di migliorare largamente l’esperienza d’uso. Ma è possibile combinarle e magari archiviare livelli di efficienza ancora maggiori? Sì! Un calderone congeniato non solo è ammesso, ma anche consigliato. Impostiamo un metodo di mixing tramite esempi, mostrandone alcuni.

Prima di tutto: la soluzione omnia

<picture>

<source
	media="(min-width: 1280px)"
	sizes="50vw"
	srcset="img-200.webp 200w,

		img-400.webp 400w,
		img-800.webp 800w,
		img-1200.webp 1200w,
		img-1600.webp 1600w,
		img-2000.webp 2000w"
	type="image/webp">

<source

	sizes="(min-width: 640px) 60vw, 100vw" 
	srcset="img-closeup-200.webp 200w,
		img-closeup-400.webp 400w, 
		img-closeup-800.webp 800w, 
		img-closeup-1200.webp 1200w, 
		img-closeup-1600.webp 1600w, 
		img-closeup-2000.webp 2000w"
	type="image/webp">

<source

	media="(min-width: 1280px)" 
	sizes="50vw"
	srcset="img-200.jpg 200w,

		img-400.jpg 400w,
		img-800.jpg 800w,
		img-1200.jpg 1200w,
		img-1600.jpg 1800w,
		img-2000.jpg 2000w">

<img
	src="img-closeup-400.jpg" alt=" "
	sizes="(min-width: 640px) 60vw, 100vw" 
	srcset="img-closeup-200.jpg 200w,
		img-closeup-400.jpg 400w, 
		img-closeup-800.jpg 800w,
		img-closeup-1200.jpg 1200w,
		img-closeup-1600.jpg 1600w,
		img-closeup-2000.jpg 2000w">
</picture>

Formati diversi e Art Direction

<picture>
	<source
		media="(min-width: 1024px)" srcset="img.webp" type="image/webp">
	<source
		media="(min-width: 1024px)" srcset="img.jpg">
	<source
		srcset="img-closeup.webp" type="image/webp">
	<img
		src="img-closeup.jpg" alt=" ">
</picture>

Immagini per schermi HDPI e Art Direction

<picture>
	<source
		media="(min-width: 1024px)"
		srcset="img-1x.jpg 1x,
			img-2x.jpg 2x,
			img-3x.jpg 3x">
	<img
		src="img-closeup-1x.jpg" alt="" 
		srcset="img-closeup-2x.jpg 2x,
			img-closeup-3x.jpg 3x">
</picture>

Formati diversi e schermi HDPI

<picture>
	<source
		srcset="img-1x.webp 1x,
			img-2x.webp 2x,
			img-3x.webp 3x"
		type="image/webp">
	<img
		src="img-1x.jpg" alt="" 
		srcset="img-2x.jpg 2x,
			img-3x.jpg 3x">
</picture>

Art Direction, formati diversi e immagini in HDPI

<picture>
	<source
		media="(min-width: 1024px)" 
		srcset="img-1x.webp 1x,
			img-2x.webp 2x, 
			img-3x.webp 3x"
		type="image/webp">
	<source
		media="(min-width: 1024px)" 
		srcset="img-1x.jpg 1x,
			img-2x.jpg 2x,
			img-3x.jpg 3x">
	<source
		srcset="img-closeup-1x.webp 1x,
			img-closeup-2x.webp 2x,
			img-closeup-3x.webp 3x"
		type="image/webp">
	<img
		src="img-closeup-1x.jpg" alt=" "
		srcset="img-closeup-2x.jpg 2x,
			img-closeup-3x.jpg 3x">
</picture>

Variable width e formati diversi

<picture>
	<source
		sizes="(min-width: 640px) 60vw, 100vw"
		srcset="img-200.webp 200w,
			img-400.webp 400w,
			img-800.webp 800w,
			img-1200.webp 1200w"
		type="image/webp">
	<img
		src="img-400.jpg" alt=""
		sizes="(min-width: 640px) 60vw, 100vw" 
		srcset="img-200.jpg 200w,
			img-400.jpg 400w,
			img-800.jpg 800w,
			img-1200.jpg 1200w">
</picture>

Variabile width, formati diversi e Art Direction

<picture>
	<source
		media="(min-width: 1280px)"
		sizes="50vw"
		srcset="img-200.webp 200w,
			img-400.webp 400w,
			img-800.webp 800w,
			img-1200.webp 1200w"
		type="image/webp">
	<source
		sizes="(min-width: 640px) 60vw, 100vw"
		srcset="img-closeup-200.webp 200w,
			img-closeup-400.webp 400w,
			img-closeup-800.webp 800w,
			img-closeup-1200.webp 1200w"
		type="image/webp">
	<source
		media="(min-width: 1280px)"
		sizes="50vw"
		srcset="img-200.jpg 200w,
			img-400.jpg 400w,
			img-800.jpg 800w,
			img-1200.jpg 1200w">
	<img
		src="img-closeup-400.jpg" alt=""
		sizes="(min-width: 640px) 60vw, 100vw"
		srcset="img-closeup-200.jpg 200w,
			img-closeup-400.jpg 400w,
			img-closeup-800.jpg 800w,
			img-closeup-1200.jpg 1200w">
</picture>

Variable width, HDPI, Art Direction

<picture>
	<source
		media="(min-width: 1280px)"
		sizes="50vw"
		srcset="img-200.jpg 200w,
			img-400.jpg 400w,
			img-800.jpg 800w,
			img-1200.jpg 1200w,
			img-1600.jpg 1600w,
			img-2000.jpg 2000w">
	<img
		src="img-closeup-400.jpg" alt=""
		sizes="(min-width: 640px) 60vw, 100vw"
		srcset="img-closeup-200.jpg 200w,
			img-closeup-400.jpg 400w,
			img-closeup-800.jpg 800w,
			img-closeup-1200.jpg 1200w,
			img-closeup-1600.jpg 1600w,
			img-closeup-2000.jpg 2000w">
</picture>

Alcune considerazioni finali

Nessun polyfill o script Javascript, just ol ‘plain HTML. Supporto nativo già disponibile. E i tuoi visitatori ti ringrazieranno. Sono un sacco di incentivi, dopotutto “cosa possono fare LORO per me?”.

Utenti più felici, e magari, bounce rate maggiore. Ecco cosa.

L'autore

Gianluca è un web designer e sviluppatore freelance con un'inspiegabile passione per i #FA7A55 design. Ha deciso di trattare di usabilità e darsi un tono, ma come logo ha scelto un cupcake. Lettore avido, perfezionista mai contento, sogna di avere un iMac, un giorno.

Sito web dell'autore | Altri articoli scritti da

Articoli correlati

Potresti essere interessato anche ai seguenti articoli:

9 commenti

Trackback e pingback

Non ci sono trackback e pingback disponibili per questo articolo