L'elemento picture è una sorta di contenitore, che di per sé non produce un output ma avverte il browser che gli oggetti in esso contenuti sono delle immagini. Al suo interno troviamo uno o più elementi source
con gli indirizzi di diverse immagini: il client sceglierà tra queste quale caricare in base alla risoluzione dello schermo (o della finestra)
Il tag picture può anche contenere uno o più elementi che offrano ai browser obsoleti soluzioni di fallback: è possibile, infatti, inserire sia un elemento img
, sia elementi testuali, come p
e span
.
In linea generale, picture
è strutturato come segue:
<picture>
<source srcset="small.jpg">
<source media="(min-width: 480px)" srcset="medium.jpg">
<source media="(min-width: 1024px)" srcset="large.jpg">
<img src="fallback.jpg">
</picture>
Nella specifica si legge che picture
viene utilizzato per visualizzare un'immagine che può provenire da una serie di origini. L'immagine utilizzata dal browser dipenderà dall'elemento source
, e più specificamente, dai suoi attributi media
, type
e srcset
.
Source
L'elemento source è utilizzato come nodo discendente degli elementi audio e video, ma l'ambito di utilizzo e gli attributi ammessi cambiano con l'introduzione dell'elemento picture
: viene superato l'attributo src
, invece previsto in audio
e video
, ed è diverso l'algoritmo di selezione della risorsa.
L'attributo media permette di stabilire una media query che il browser colloca in un foglio di stile nell'ordine in cui i rispettivi elementi source vengono definiti nel documento. Se manca l'attributo media
, questo viene interpretato come media="all"
. Qualunque valore non valido viene ignorato dal browser.
La tabella che segue elenca gli attributi così come descritti dal WHATWG:
Attributo | Descrizione |
---|---|
srcset | obbligatorio, deve essere composto da una o più stringhe (image candidate string), separate tra loro da virgola. La stringa deve essere composta da una valida URL, un eventuale spazio bianco, un eventuale descrittore di larghezza o di densità. |
sizes | se presente, il valore deve essere costituito da un elenco valido di dimensioni (em, rem, px, etc.). |
media | se presente, deve rappresentare una valida media query. |
type | se presente, il valore deve essere un valido MIME type. Un tipo non supportato implica che il browser passi alla risorsa successiva (come avviene nel caso di video e audio ). |
Img e srcset
Nelle proposte di sviluppo, gli attributi srcset
e sizes non estendono solo l'elemento picture
, ma anche con l'elemento img
, così da fornire anche a quest'ultimo un elenco di dimensioni e corrispondenti risorse.
Ecco un primo esempio di utilizzo dell'attributo srcset
con l'elemento img
:
<img
src="images/pieve_1024.jpg"
srcset="images/pieve_1024.jpg 1024w, images/pieve_800.jpg 800w, images/pieve_640.jpg 640w, images/pieve_480.jpg 480w"
alt="La pieve di San Leo" />
In questo esempio, il browser sceglierà una delle quattro immagini elencate come valore dell'attributo srcset
in base alla larghezza del viewport.
Quando usare picture e quando usare img
Si ricorre all'elemento picture
quando il progetto responsive prevede di fornire immagini diverse a diversi tipi di schermo (art direction), oppure quando le immagini vengono fornite in differenti formati (attributo type
).
Su html5test.com è possibile verificare quali sono i formati grafici supportati dallo user agent (l'immagine si riferisce a Firefox 30.0)
L'elemento picture
, quindi, non va genericamente a sostituire l'elemento img
. Infatti, il Responsive Images Community Group raccomanda di ricorrere all'elemento img
quando l'immagine ha un'unica origine, oppure quando viene fornita allo user agent la stessa immagine in differenti densità (quindi senza "art direction", ovvero la sostituzione dell'immagine con un dettaglio o un'altra immagine).
Esempi
Alcuni esempi illustreranno le casistiche più comuni.
Stessa immagine a più risoluzioni
In questo caso viene fornita una copia esatta della stessa immagine, con la sola differenza della risoluzione (640, 800 e 1024px):
<img
src="images/pieve_640.jpg"
srcset="images/pieve_800.jpg 1.5x, images/pieve_1024.jpg 2x"
alt="La pieve di San Leo" />
Il browser caricherà una delle tre immagini a seconda della densità dello schermo del client. Per ragioni di retro-compatibilità, viene specificato anche il valore dell'attributo src
, che fornisce l'immagine a risoluzione inferiore.
Il device pixel ratio del Samsung Galaxy 4 mini è pari a 1.5x
Immagini diverse su periferiche diverse: Art direction
È pratica comune quella di fornire immagini leggermente diverse a periferiche diverse. Ai browser mobili, ad esempio, si può fornire un particolare ingrandito dell'immagine originale. In questo caso è raccomandato il ricorso all'elemento picture
e ad un elemento source
per ognuna delle immagini previste:
<picture>
<source media="(min-width: 45em)" srcset="images/pieve_1024.jpg">
<source media="(min-width: 18em)" srcset="images/pieve_480.jpg">
<img src="images/pieve_480.jpg" alt="La pieve di San Leo">
<p>Testo accessibile</p>
</picture>
Dimensioni dello schermo e densità
All'interno dello stesso elemento source
possono essere stabiliti diversi criteri di selezione, assegnando un valore all'attributo media
e più valori valori all'attributo srcset
.
<picture>
<source media="(min-width: 45em)" srcset="images/large_1024.jpg, images/large_1600.jpg 2x">
<source media="(min-width: 18em)" srcset="images/small_640.jpg, images/small_1024.jpg 2x">
<img src="images/large_1024.jpg" alt="Omino al lavoro">
<p>Testo accessibile</p>
</picture>
In questo caso il browser individua prima l'elemento source
in base alle dimensioni dello schermo (attributo media), quindi seleziona l'origine dell'immagine in base alla densità video della periferica.
La selezione in base alla viewport
Spesso le dimensioni effettive dell'immagine ci sono ignote in fase di progettazione, magari perché variano in proporzione rispetto alla viewport. Un'immagine di 600px che occupi l'intera larghezza dello schermo, ad esempio, corrisponde approssimativamente a 2x
su uno schermo di 320px di larghezza, ma a meno di 1x
su un tablet o un desktop.
In situazioni simili, possiamo ricorrere all'attributo sizes dell'elemento img
, come nel seguente esempio:
<img
sizes="100vw"
srcset="images/mare_400.jpg 400w, images/mare_800.jpg 800w, images/mare_.jpg 1600w" src="pic400.jpg"
alt="Scorcio del promontorio di Taormina" />
In questo caso, invece di specificare la densità per ogni immagine, viene specificata direttamente la dimensione di ognuna, in modo che il browser selezioni quella che meglio si adatti alla larghezza dello schermo. Allo stesso tempo, viene passata l'informazione, attraverso l'attributo sizes
, che l'elemento img
occuperà il 100% del viewport (vw
è una delle unità di misura definite viewport units).
Invece di indicare al browser le dimensioni delle immagini, avremmo potuto calcolare la densità orizzontale dell'immagine: su uno schermo di 320px, un'immagine di 400px avrebbe avuto una densità pari a 400/320 = 1,25x
. Su uno schermo di 1240px, invece, un'immagine di 400px corrisponderebbe ad una densità di .32x
. Se cambiano le dimensioni dello schermo, quindi, cambia anche la densità delle immagini.
Selezione in base ai breakpoint del layout
Una media query fissa un breakpoint nel layout, ossia un limite riferito alle dimensioni del viewport, raggiunto il quale si passa da un layout ad un altro.
Ancora una volta, se non si sta facendo dell'art direction e le URL puntano a copie di dimensioni diverse della stessa immagine, l'elemento img
offre la soluzione più efficiente. Prendiamo ad esempio il seguente codice:
<img
sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)"
srcset="images/mare_100.jpg 100w, images/mare_200.jpg 200w, images/mare_400.jpg 400w, images/mare_800.jpg 800w, images/mare_.jpg 1600w"
src="images/mare_400.jpg"
alt="Scorcio del promontorio di Taormina" />
In questo esempio abbiamo fissato tre breakpoints: fino a 30em, l'immagine occuperà l'intera larghezza del viewport; da 30 a 50em, sarà proporzionata al 50% della larghezza disponibile; oltre i 50em, le dimensioni dell'immagine saranno calcolate per corrispondere al 33% del viewport meno 100px.
Fissati i breakpoint, sarà il browser a scegliere l'immagine che meglio si adatti alle dimensioni e alla densità dello schermo, con gran sollievo dello sviluppatore, che dovrà limitarsi a fornire un congruo numero di copie dell'immagine in diverse dimensioni.
Se avessimo fatto ricorso all'elemento picture
, avremmo dovuto aggiungere un elemento source
per ognuna delle media query utilizzate. La soluzione offerta dall'elemento img
e dall'attributo sizes, invece, permette di ridurre il codice al minimo garantendo lo stesso risultato.
Il supporto dei browser
Al momento nessun browser supporta l'elemento picture
, ma la non dovremmo essere lontani dalla sua introduzione: è già tra le feature di Chrome Canary e sia Firefox che Webkit non tarderanno ad implementare il nuovo elemento. Per questo motivo gli esempi riportati si basano soprattutto sulle risorse messe a disposizione dal Responsive Images Community Group. In particolare, si è fatto riferimento al draft della specifica. Il documento originale è ora migrato nella sezione Embedded Content dell'HTML Living Standard del WHATWG, disponibile anche nella versione developers.
Dunque è il momento di sperimentare, e lo strumento più adatto al momento è il polifill Picturefill, che, oltre a fornire la libreria JS che permette di utilizzare gli elementi e gli attributi di cui abbiamo discusso, offre una serie di esempi di codice pronto per l'uso.
Risorse online
L'analisi del problema delle immagini responsive è sviluppata nel dettaglio nell'ambito del progetto dell'RICG. Un'attenta disamina è disponibile all'indirizzo http://usecases.responsiveimages.org/.
La Device pixel ratio indica la densità video di una periferica. Per un'analisi più approfondita della densità video e del rapporto tra pixel fisici e astratti, rinviamo alla lettura dei seguenti articoli di Quirksmode:
Esiste un utile strumento online che permette di verificare l'indicatore di densità sulla propria periferica all'indirizzo http://www.devicepixelratio.com/
Il discorso sull'Art direction, qui solo accennato, può essere approfondito con la lettura dell'articolo Art direction and design di A List Apart