MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

Immagini reattive

Questa traduzione è incompleta. Collabora alla traduzione di questo articolo dall’originale in lingua inglese.

In questo articolo impareremo il concetto di "immagini reattive" (responsive images) — immagini che funzionano correttamente su dispositivi con monitor di dimensioni e risoluzioni  anche molto diverse — e vedremo quali strumenti l'HTML ci mette a disposizione per implementarle. Le immagini reattive sono solo una parte della progettazione di un web reattivo (responsive web design), e pongono delle buone basi per un argomento del quale si imparerà molto di più in un modulo seguente sui CSS.

Prerequisiti: Dovresti già conoscere basics of HTML e come aggiungere immagini a una pagina web.
Obiettivi: Imparare ad usare caratteristiche quali l'attributo srcset e l'elemento <picture> per aggiungere immagini reattive ai siti web, usando diverse soluzioni.

Perché le immagini reattive?

Quale problema stiamo cercando di risolvere con le immagini reattive? Esaminiamo uno scenario tipico. Un sito web, probabilmente, avrà una immagine di testa (header image) per piacere ai visitatori, più, forse, altre immagini più giù nel contenuto. Probabilmente si vorrà che l'immagine di testa occupi l'intera larghezza della pagina e che le immagini nel contenuto riempiano le colonne. Vediamo un esempio:

Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center.

Ciò funziona bene su un dispositivo con uno schermo ampio, come un laptop o un desktop (you can see the example live and find the source code on Github). Non discuteremo molto dei CSS, salvo che per dire questo:

  • il contenuto del body è stato fissato ad una larghezza massima di 1200 pixels — sopra a questa larghezza il body rimarrà a 1200px e si centrerà orizzontalmente nella pagina. Sotto a questa larghezza, il body verrà visualizzato al 100% della larghezza della pagina.
  • L'immagine di testa è impostata in modo che il suo centro sia sempre nel centro della testata, indipendentemente dalla larghezza della stessa. Così, se il sito è visto in uno schermo più stretto, i dettagli importanti nel centro dell'immagine (le persone) rimangono visibili, mentre ai lati viene perso ciò che eccede. L'altezza è di 200 px.
  • Le immagini nel contenuto sono impostate in modo che se l'elemento body diventa più stretto delle immagini, queste iniziano a ridursi per rimanere sempre al''interno del body, piuttosto che strabordare.

Così va bene, ma il problema arriva quando cominci a vedere il sito su un dispositivo con uno schermo stretto — l'immagine di testata si vede bene, ma inizia a prendere gran parte dell'altezza dello schermo per un dispositivo portatile; d'altra parte la prima immagine del contenuto si vede malissimo - a questa dimensione si possono appena vedere le persone.

Our example site as viewed on a narrow screen; the first image has shrunk to the point where it is hard to make out the detail on it.

Quando il sito è visualizzato su uno schermo stretto, sarebbe molto meglio mostrare una versione ritagliata dell'immagine che contenga i dettagli importanti dello scatto e magari una via di mezzo tra le due foto quando lo schermo è di media dimensione, come per i tablet. - Questa situazione è nota come art direction problem.

Inoltre, non c'è bisogno di includere immagini così grandi se la pagina vien vista sui piccoli schermi dei portatili. - Questa è nota come resolution switching problem. Una immagine raster è definita da un certo numero di pixel di larghezza e da un certo numero in altezza; come abbiamo visto parlando di vector graphics, una immagine raster inizia a sgranarsi e a sfocarsi se è mostrata più grande della sua dimensione originale (ciò non accade per le immagini vettoriali), mentre se la visualizziamo più piccola stiamo sprecando banda per far scaricare un file immagine più pesante del necessario - specialmente gli utenti di dispositivi portatili non vogliono che questo accada dal momento che una piccola immagine farebbe a caso loro. Una soluzione ideale la si avrebbe se si avessero diverse immagini, con diverse dimensioni e risoluzioni, da caricare sui diversi dispositivi.

A rendere le cose ancora più complicate, hanno schermi ad alta risoluzione che necessitano di immagini più grandi di quello che ci si potrebbe aspettare per apparire al meglio. Questo problema è essenzialmente analogo, ma in un contesto leggermente diverso.

Si potrebbe pensare che le immagini vettoriali possano risolvere questi problemi e in certa misura lo fanno: sono leggere, vengono scalate (ingrandite in scala) bene e dove possibile le si dovrebbe usare. Tuttavia non sono adatte a qualsiasi tipo di immagine: mentre sono ottime per grafiche semplici, cominciano a diventare molto complesse per creare immagini con il livello di dettaglio che si vorrebbe per una foto. Le immagini raster dei formati come ad es. JPEG sono più adatte ai tipi di immagini che abbiamo visto negli esempi precedenti.

Questo tipo di problemi non esisteva quando il web era agli esordi, nei primi anni 90: allora, gli unici dispositivi esistenti per navigare il web erano i desktop e i laptop, così i progettisti di browser e gli scrittori non dovevano pensare alle soluzioni. Le tecnologie per le immagini reattive (Responsive image technologies) sono state aggiunte di recente per risolvere i problemi accennati sopra, permettendoti di fornire al browser diversi file immagine, che contengono le stesse immagini ma ad una risoluzione diversa, con diverso numero di pixel (resolution switching), o immagini diverse adatte a spazi di allocazione di dimensione diversa (art direction.)

Nota: Le nuove caratteristiche trattate in questo articolo — srcset/sizes/<picture> — sono tutte supportate nelle versioni più aggiornate dei browser per desktop e per dispositivi mobili (incluso il browser Microsoft Edge, non da Internet Explorer.) 

Come creare immagini reattive?

In questa sezione, esamineremo i 2 problemi illustrati e mostreremo come risolverli usando le caratteristiche dell'HTML per le immagini reattive. Dovreste notare che ci concentreremo sull'elemento <img> come trattato nell'esempio precedente — l'immagine nella header è solo decorativa e perciò è aggiunta usando i CSS. I CSS hanno probabilmente migliori strumenti per il responsive design dell'HTML; ne parleremo in un successivo modulo sui CSS.

Cambiare risoluzione: dimensioni differenti

Qual è il problema che vogliamo risolvere cambiando la risoluzione? Vogliamo mostrare una immagine identica, ma più grande o più piccola in funzione del dispositivo — è la situazione che abbiamo con la seconda immagine del nostro esempio. L'elemento standard <img> tradizionalmente, permette solo di puntare a un singolo file sorgente.

<img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

Tuttavia, possiamo usare 2 nuovi attributi — srcset e sizes — per fornire molte sorgenti di immagine addizionali insieme a dei suggerimenti per aiutare il browser a prelevare quella giusta. Si può vedere un esempio nel nostro reponsive.html su Github (vedere anche il codice sorgente):

<img srcset="elva-fairy-320w.jpg 320w,
             elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 320px) 280px,
            (max-width: 480px) 440px,
            800px"
     src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">

Gli attributi srcset e sizes sembrano complicati da capire, ma non lo sono poi tanto se li si formatta come mostrato qui sopra: con una parte del valore dell'attributo per riga. Ogni valore contiene una lista  separata da virgole e ogni parte della lista è fatta di 3 sottoparti. Esaminiamo il contenuto di ognuna:

srcset definisce il set di immagini tra le quali vogliamo che il browser scelga e quali dimensioni hanno. Prima di ogni virgola, scriviamo:

  1. un nome di file immagine (elva-fairy-480w.jpg.)
  2. uno spazio
  3. la dimensione della larghezza dell'immagine in pixels (480w) — notate l'uso dell'unità w e non px come ci si potrebbe aspettare. Si tratta della reale dimensione dell'immagine, che si può trovare esaminando il file immagine sul computer (per esempio in un Mac si può selezionare l'immagine in  Finder, e premere Cmd + I per aprire la scheramta di informazioni).

sizes definisce un set di condizioni (ad es. la larghezza dello schermo) e indica quale dimensione di immagine sarebbe meglio scegliere quando si verificano quelle condizioni — questi sono i suggerimenti di cui si parlava prima. In questo caso, prima di ogni virgola scriviamo:

  1. una media condition ((max-width:480px)) — imparerete di più a questo riguardo nella sezione sui CSS, ma per adesso diciamo solo che la "media condition" descrive un possibile stato dello schermo. In questo caso, si stà dicendo: "quando la larghezza visualizzata è 480 pixels o meno".
  2. uno spazio
  3. La larghezza della posizione che l'immagine occuperà quando si realizza la condizione (440px.)

Nota: Per la larghezza della posizione, si può fornire una misura assoluta (px, em) o una relativa (come una percentuale). Potreste aver notato che l'ultima larghezza non ha media condition — questa è perciò la condizione di default che deve essere scelta quando nessuna delle condizioni sui dispositivi è vera. Il browser ignora tutto ciò che segue la prima condizione verificata, perciò bisogna fare attenzione all'ordine delle condizioni.

Quindi, definiti questi attributi, il browser farà:

  1. verifica della larghezza del suo dispositivo
  2. calcolo di quale sia la prima condizione tra la lista dell'atributo sizes ad essere vera
  3. Look at the slot size given to that media query.
  4. Caricamento dell'immagine elencata nell'attributo srcset che maggiormente si avvicina alla dimensione della posizione (slot) scelta.

Fatto! Così a questo punto, se un browser col supporto con una larghezza della viewport di 480px carica la pagina, la (max-width: 480px) media condition sarà vera, perciò verrà scelta la slot da 440px, quindi sarà caricata la elva-fairy-480w.jpg, poiché la sua larghezza (480w) è la più vicina ai 440px. L'immagine da 800px occupa 128KB su disco, mentre la versione da 480px solo 63KB — un risparmio di 65KB. Adesso immagina se fosse una pagina con molte immagini. Usando questa tecnica si può far risparmiare agli utenti mobile un sacco di  ampiezza di banda.

I browser più vecchi che non supportano queste caratteristiche, semplicemente le ignoreranno e andranno avanti a caricare l'immagine indicata dall'attributo src come al solito.

Note: nell'elemento <head> del documento si troverà la linea <meta name="viewport" content="width=device-width">: questo obbliga i browser dei dispositivi mobili ad adottare la loro reale larghezza viewport per caricare le pagine web (alcuni browser mentono riguardo alla larghezza e caricano invece pagine a una risoluzione maggiore e poi la riducono, che non è molto utile con una progettazione o una immagine reattiva. Spiegheremo di più a questo proposito in un modulo successivo).

Utili strumenti di sviluppo

Ci sono alcuni utili developer tools nei browser, per aiutare a calcolare le necessarie larghezze slot, ecc. che si ha bisogno di usare. Mentre le stavo calcolando, prima di tutto ho caricato la versione non reattiva dell'esempio (not-responsive.html), poi sono andato in Responsive Design View (Tools > Web Developer > Responsive Design View - In Firefox, dal sandwich menù -> Sviluppo -> Modalità visualizzazione flessibile), che ti permette di guardare il layout della tua pagina come se fosse visto attraverso dispositivi con diversa dimensione dello schermo.

Ho impostato la larghezza viewport a 320px e poi a 480px; per ciascuna sono andato nel DOM Inspector, ho cliccato sull'elemento <img> a cui ero interessato e ho guardato la dimensione nella scheda vista Box Model sulla destra del monitor. Questo dovrebbe dare la larghezza dell'immagine di cui si ha bisogno.

A screenshot of the firefox devtools with an image element highlighted in the dom, showing its dimensions as 440 by 293 pixels.

Dopo, si può controllare se srcset sta funzionando impostando la larghezza viewport come si desidera (impostatela stretta, per esempio), aprendo il Network Inspector (Tools > Web Developer > Network), poi ricaricando la pagina. Questo dovrebbe dare una lista di risorse che sono state scaricate per per mostrare la pagina e quindi si potrà verificare quale file è stato scelto e scaricato.

a screenshot of the network inspector in firefox devtools, showing that the HTML for the page has been downloaded, along with three images, which include the two 800 wide versions of the responsive images

Modificare la risoluzione: stessa dimensione, diverse risoluzioni

Se stai supportando diverse risoluzioni, ma tutti vedono la tua immagine alla stessa dimensione reale sullo schermo, puoi permettere al browser di scegliere una immagine di risoluzione appropriata usando l'attributo srcset con il descrittore x (x-descriptors) e senza sizes — una sintassi piuttosto semplice! Puoi trovare un esempio di come appare in srcset-resolutions.html (vedere anche il codice sorgente):

<img srcset="elva-fairy-320w.jpg,
             elva-fairy-480w.jpg 1.5x,
             elva-fairy-640w.jpg 2x"
     src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">

A picture of a little girl dressed up as a fairy, with an old camera film effect applied to the imageIn questo esempio è stato applicato il seguente CSS all'immagine per farle avere una larghezza di 320 pixels sullo schermo (also called CSS pixels):

img {
  width: 320px;
}

In questo caso sizes non è necessario — il browser calcola qual è la risoluzione del display su cui è mostrato e fornisce l'immagine più appropriata tra quelle elencate in srcset. Così se il dispositivo che accede alla pagina ha un display standard a bassa risoluzione, with one device pixel representing each CSS pixel, viene caricata l'immagine elva-fairy-320w.jpg (il descrittore 1x è implicito e non c'è bisogno di specificarlo.) Se il dispositivo ha una alta risoluzione di 2 pixel per ogni pixel CSS o più, viene caricata l'immagine elva-fairy-640w.jpg. L'immagine a 640px è di 93KB, mentre quella a 320px è di soli 39KB.

Art direction

To recap, the art direction problem involves wanting to change the image displayed to suit different image display sizes. For example, if a large landscape shot with a person in the middle is shown on a website when viewed on a desktop browser, then shrunk down when the website is viewed on a mobile browser, it will look bad as the person will be really tiny and hard to see. It would probably be better to show a smaller, portrait image on mobile, which shows the person zoomed in. The <picture> element allows us to implement just this kind of solution.

Returning to our original not-responsive.html example, we have an image that badly needs art direction:

<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">

Let's fix this, with <picture>! Like <video> and <audio>, The <picture> element is a wrapper containing several <source> elements that provide several different sources for the browser to choose between, followed by the all-important <img> element. the code in responsive.html looks like so:

<picture>
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva">
</picture>
  • The <source> elements include a media attribute that contains a media condition — as with the first srcset example, these conditions are tests that decide which image is shown — the first one that returns true will be displayed. In this case, If the viewport width is 799px wide or less, the first <source> element's image will be displayed. If the viewport width is 800px or more, it'll be the second one.
  • The srcset attributes contain the path to the image to display. Note that just as we saw with <img> above, <source> can take a srcset attribute with multiple images referenced, and a sizes attribute too. So you could offer multiple images via a <picture> element, but then also offer multiple resolutions of each one too. Realistically, you probably won't want to do this kind of thing very often.
  • In all cases, you must provide an <img> element, with src and alt, right before </picture>, otherwise no images will appear. This provides a default case that will apply when none of the media conditions return true (you could actually remove the second <source> element in this example), and a fallback for browsers that don't support the <picture> element.

This code allows us to display a suitable image on both wide screen and narrow screen displays, as shown below:

Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center.Our example site as viewed on a narrow screen with the picture element used to switch the first image to a portrait close up of the detail, making it a lot more useful on a narrow screen

Note: You should use the media attribute only in art direction scenarios; when you do use media, don't also offer media conditions within the sizes attribute.

Why can't we just do this using CSS or JavaScript?

When the browser starts to load a page, it starts to download (preload) any images before the main parser has started to load and interpret the page's CSS and JavaScript. This is a useful technique, which on average has shaved 20% off page load times. However, it is not helpful for responsive images, hence the need to implement solutions like srcset. You couldn't for example load the <img> element, then detect the viewport width with JavaScript and dynamically change the source image to a smaller one if desired. By then, the original image would already have been loaded, and you would load the small image as well, which is even worse in responsive image terms.

Use modern image formats boldly

There are several exciting new image formats (such as WebP and JPEG-2000) that can maintain a low file size and high quality at the same time. However, browser support is spotty.

<picture> lets us continue catering to older browsers. You can supply MIME types inside type attributes so the browser can immediately reject unsupported file types:

<picture>
  <source type="image/svg+xml" srcset="pyramid.svg">
  <source type="image/webp" srcset="pyramid.webp"> 
  <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles">
</picture>
  • Do not use the media attribute, unless you also need art direction.
  • In a <source> element, you can only refer to images of the type declared in type.
  • As before, you're welcome to use comma-separated lists with srcset and sizes, as needed.

Active learning: Implementing your own responsive images

For this active learning, we're expecting you to be brave and go it alone ... mostly. We want you to implement your own suitable art directed narrow screen/wide screen shot using <picture>, and a resolution switching example that uses srcset.

  1. Write some simple HTML to contain your code (use not-responsive.html as a starting point, if you like)
  2. Find a nice wide screen landscape image with some kind of detail contained in it somewhere. Create a web-sized version of it using a graphics editor, then crop it to show a smaller part that zooms in on the detail, and create a second image (about 480px wide is good for this.)
  3. Use the <picture> element to implement an art direction picture switcher!
  4. Create multiple image files of different sizes, each showing the same picture.
  5. Use srcset/size to create a resolution switcher example, either to serve the same size image at different resolutions, or different image sizes at different viewport widths.

Note: Use the browser devtools to help work out what sizes you need, as mentioned above.

Summary

That's a wrap for responsive images — we hope you enjoyed playing with these new techniques. As a recap, there are two distinct problems we've been discussing here:

  • Art direction: The problem whereby you want to serve cropped images for different layouts — for example a landscape image showing a full scene for a desktop layout, and a portrait image showing the main subject zoomed in close for a mobile layout. This can be solved using the <picture> element.
  • Resolution switching: The problem whereby you want to serve smaller image files to narrow screen devices, as they don't need huge images like desktop displays do — and also optionally that you want to serve different resolution images to high density/low density screens. This can be solved using vector graphics (SVG images), and the srcset and sizes attributes.

This also draws to a close the entire Multimedia and embedding module! The only thing to do now before moving on is to try our multimedia assessment, and see how you get on. Have fun.

See also

Tag del documento e collaboratori

 Hanno collaborato alla realizzazione di questa pagina: kalamun, howilearn
 Ultima modifica di: kalamun,