Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Dimensione flessibile delle immagini in HTML: responsive image

Tecniche, strumenti e risorse per avere immagini che si adattano al layout e al dispositivo di fruizione.
Tecniche, strumenti e risorse per avere immagini che si adattano al layout e al dispositivo di fruizione.
Link copiato negli appunti

Cosa indica l'aggettivo flessibile? In senso figurato, tutto ciò che è in grado di adattarsi a diverse situazioni.

In questo articolo, riferendolo alle immagini, lo useremo in due accezioni e contesti specifici:

  1. Immagini in grado di adattarsi alla tipologia e alle dimensioni del layout
  2. Immagini capaci di adattarsi alle caratteristiche del layout e del dispositivo su cui vengono visualizzate

Presenteremo tecniche e strumenti recentemente emersi in rete per ottenere nel modo più semplice i risultati desiderati, avendo come contesto di riferimento quello del cosiddetto responsive design.

Immagini adattabili al layout

Il contesto d'uso in cui risulta utile la tecnica che stiamo per presentare è quello dei layout non fissi, quelli cioè in cui le dimensioni non sono espresse con unità di misura assolute (pixel) e che risultano pertanto a larghezza variabile, dipendente da fattori come la larghezza della finestra del browser (layout liquidi) o la dimensione del testo (layout elastici).

Per la loro stessa natura, infatti, le immagini non sono flessibili, hanno dimensioni fisse, misurate in pixel. Lo stesso discorso è valido per oggetti come video e movie Flash. Di fatto, nelle tipologie di layout cui si è accennato qui sopra, si va ad inserire in un contesto flessibile un oggetto che non lo è.

In un layout fisso il problema non si pone. L'articolo che state leggendo è contenuto in un div largo 550px. Questa misura rappresenta un vincolo e al tempo stesso una guida: se non voglio spezzare il layout, le immagini che inserisco non devono essere più larghe di 550px. Valutando fattori come margini e padding, posso ricavare una misura ottimale, per esempio equivalente a 500px. Una volta rispettata questa semplice indicazione, non devo preoccuparmi di niente.

E in un layout flessibile? Il discorso cambia. Dal momento che le dimensioni sono espresse con unità di misura relative (em o percentuali), non sono in grado di prevedere a quanti pixel reali corrisponderanno. Non posso, per esempio, sapere su che monitor l'utente visualizzerà la pagina, quanto sarà larga la finestra del browser, quale sarà il fattore di ingrandimento del testo, etc. Inserendo immagini, che hanno delle dimensioni fisse in pixel, si corre il rischio che risultino a un certo punto poco adattate al contesto, perché troppo piccole, o perché troppo grandi.

Partiamo da questo primo esempio. La colonna del contenuto principale è a larghezza flessibile; ridimensionando la finestra del browser si nota come il testo si allarghi o si restringa nella colonna. Idealmente vorrei che le immagini (larghe 450px) fossero sempre della stessa larghezza del paragrafo in cui sono inserite. E in effetti, ridimensionando la finestra del browser, a un certo punto ottengo il risultato voluto, come si evince da questo screenshot:

Figura 1. Immagine larga 450px inserita nel corpo del testo
Immagine larga 450px inserita nel corpo del testo

Ma basta massimizzare la finestra del browser per ottenere questo risultato:

Figura 2. L'immagine visualizzata in una finestra massimizzata
L'immagine visualizzata in una finestra massimizzata

Si può decidere che va bene così e procedere. Può essere tutto sommato un compromesso accettabile.

Sicuramente da evitare sono invece situazioni come quella del secondo esempio. È stata usata un'immagine larga 950px: facile aspettarsi che essa possa uscire dai limiti della colonna centrale rovinando tutto il layout.

Ecco che a questo punto entra in gioco il concetto di immagine flessibile. L'ideale, infatti, sarebbe riuscire a far sì che le immagini si adattino automaticamente al layout. Nel nostro caso assumendo una larghezza che sia sempre pari a quella dell'elemento che le contiene.

Responsive image CSS

La soluzione è invero a portata di mano. Basta usare la proprietà CSS max-width con un valore pari al 100% e assegnarla alle immagini che vogliamo rendere flessibili. In pratica, tramite i CSS, supero il problema delle dimensioni fisse ricorrendo ad un'unità di misura relativa (le percentuali).

Nel terzo esempio abbiamo allora creato questa semplice regola CSS:

.flex {max-width: 100%}

Una classe flex da assegnare solo alle immagini che vogliamo rendere flessibili. E infatti l'abbiamo assegnata all'immagine, larga 950px, dei pini:

<p><img class="flex" src="pini.jpg" alt="pini"></p>

Il risultato è in linea con quanto ci si attende: possiamo ridimensionare la finestra del browser come e quanto ci pare, la larghezza dell'immagine corrisponderà sempre a quella dell'elemento che la contiene. E le dimensioni scalano sempre proporzionalmente.

Un momento. Qualcuno potrebbe far osservare: "Ma se si tratta semplicemente di rendere le dimensioni delle immagini flessibili tramite i CSS, perché non usare la proprietà width? Magari un bel width: 100%?". Giusta osservazione. In effetti nella maggior parte delle situazioni le due proprietà sono equivalenti, l'effetto ottenuto è identico. Ma c'è uno scenario da valutare.

Usando width: 100% invece che max-width: 100%, l'immagine viene scalata sempre e comunque. Pertanto, se ho un'immagine di 200px in un paragrafo largo più o meno 500px, il risultato sarà questo:

Figura 3. Immagine sgranata con width=100%
screenshot

L'immagine, scalata all'eccesso, risulta ovviamente sgranata, ha perso in dettaglio.

Usando invece max-width: 100%, quando l'immagine è più piccola del suo contenitore, mantiene le sue dimensioni originarie:

Figura 4. Immagine con max-width=100%
screenshot

Da questi semplici esempi possiamo ricavare un insegnamento. Volendo usare questa tecnica è utile partire da immagini piuttosto ampie in larghezza che verranno poi ridimensionate con max-width per adattarsi al contesto. La scelta delle dimensioni ideali dipenderà ovviamente da caso a caso.

Un problema con Windows e uno con IE6

Il merito di aver per la prima volta divulgato la tecnica max-width: 100% per rendere le immagini flessibili spetta a Richard Rutter, che ha presentato sul suo sito gli esiti dei test che ha condotto.

A migliorarla, risolvendo un problema piuttosto serio nella resa a schermo, è stato Ethan Marcotte. Nell'articolo Fluid Images, pone il caso di alcuni browser (vecchie versioni di Firefox, IE versione 7.0 e precedenti) che su Windows offrono, in presenza di questa tecnica, un degrado pesante delle immagini quando esse vengono ridimensionate.

La soluzione, basata su un semplice script Javascript e sull'uso di una minuscola GIF trasparente di 1x1px, sfrutta il filtro proprietario di Microsoft AlphaImageLoader. L'abbiamo implementata nell'ultimo esempio, e trovate tutti i file adoperati nel file allegato all'articolo.

Se la compatibilità piena con quei browser è una necessità assoluta, potete sfruttarla.

Allo stesso modo, dal momento che IE6 non supporta la proprietà max-width, si può servire a quel browser l'alternativa basata su width: 100%, magari all'interno di un commento condizionale:

<!--[if IE 6]>
<style type="text/css">
.flex {width: 100%}
</style>
<![endif]-->

Immagini che si adattano al dispositivo

La tecnica appena vista può essere un ottimo punto di partenza anche per adattare le immagini quando esse vengono visualizzate su dispositivi mobili.

In quel contesto, però, si può procedere oltre sulla via dell'adattamento. Non solo si dovrebbe fare in modo che le immagini si adattino a livello di layout, ma sarebbe ideale servirle all'utente in una forma ottimizzata nelle dimensioni e nel peso. Detto diversamente: perché inviare all'utente di un iPhone una pesantissima foto di 2000x1200px quando la risoluzione dello schermo di quel dispositivo è infinitamente inferiore? È oggettivamente uno spreco in uno scenario in cui disponibilità di banda e velocità della connessione sono fattori cruciali.

Partendo da questa semplice considerazione, sono state sviluppate tecniche che mirano a servire immagini adatte al contesto di fruizione, ovvero al dispositivo e/o alla risoluzione dello schermo.

Alcune di queste tecniche sono basate su soluzioni client-side, sfruttando per esempio i soli CSS o facendo ricorso a Javascript.

In verità, quelle al momento più promettenti contemplano tutte una qualche forma di elaborazione lato server. Ciò si rende necessario principalmente per un motivo: se servo all'utente iPhone un'immagine di 400x300px e a chi usa un potente e fiammante PC una di 2000x1200px, devo fare in modo che i browser dei rispettivi sistemi non scarichino entrambe le versioni.

La prima soluzione che vedremo cerca di rispondere proprio a questa esigenza.

Responsive images di Filament Group

Si tratta di un esperimento targato Filament Group che prevede la combinazione di uno script Javascript e di una semplice elaborazione lato server. I file necessari per implementare la tecnica sono disponibili per il download da GitHub.

Come operazione preliminare dovremo avere a disposizione due versioni differenti di una stessa immagine, una pensata per i desktop e/o per schermi ad alta risoluzione, un'altra ottimizzata per dispositivi mobili.

Nel nostro esempio abbiamo usato un'immagine di 700x534px e una di 320x213px.

Una volta scompattato il pacchetto zip, oltre ad una demo, troviamo al suo interno i due file che ci servono.

Il primo è un file .htaccess. Va aggiunto alla directory root del sito. È il file che gestisce, tramite il modulo mod_rewrite di Apache, l'indirizzamento all'utente dell'immagine adatta. Se abbiamo già attivo sul server un file .htaccess, si può copiare e incollare in quest'ultimo il contenuto del file .htaccess di Filament Group.

Il secondo file necessario è 'responsiveimgs.js' (nello zip è presente anche una versione compressa dello script). Il file va richiamato nella sezione <head> della pagina:

<script src="responsiveimgs.js"></script>

L'operazione fondamentale che compie è quella di intercettare le dimensioni dello schermo: in base alla larghezza, verrà servita all'utente un'immagine a piena risoluzione o un'immagine adattata per dispositivi mobili, ottimizzata nel peso e nelle dimensioni. Di default, viene servita l'immagine piccola quando la larghezza dello schermo è pari o inferiore a 480px. Possiamo impostare un valore diverso inserendo prima dello script, nel codice HTML del documento, queste semplici righe di configurazione:

<script>
var rwd_images = {
widthBreakPoint: 600
};
</script>
<script src="responsiveimgs.js"></script>

Non ci resta che definire nel codice HTML il riferimento all'immagine. Dovremo usare una sintassi di questo tipo:

<img src="immagine_piccola.jpg?full=immagine_grande.jpg" />

In pratica, per tutte le immagini di cui vogliamo fornire una doppia versione, useremo nella src il riferimento all'immagine piccola, quella per il mobile, seguito da una query string ?full= che precede il riferimento all'immagine ad alta risoluzione. Ecco il codice che abbiamo usato nell'esempio:

<img src="pini_small.jpg?full=pini_large.jpg" />

Tutto qui. I browser che non hanno Javascript attivo otterranno l'immagine piccola. Browser datati come IE6/7 o Firefox 3.0 scaricheranno entrambe le immagini.

Ecco ancora il link all'esempio. Il consiglio è quello di aprire la pagina anche con un browser mobile.

Nella seconda parte dell'articolo vedremo come ottenere immagini flessibili sfruttanto i cookies

La tecnica sviluppata da Keith Clark è basata su una combinazione tra cookie e PHP. L'implementazione è estremamente semplice.

Di base, lo script può gestire fino a 3 versioni di una stessa immagine. Una versione piccola per schermi con larghezza inferiore a 800px, una versione media per schermi tra 800px e 1024px, una versione standard per schermi ad alta risoluzione.

Il primo passo per l'implementazione consiste nell'inserire nella <head> del documento questa riga di Javascript:

<script>
document.cookie = "device_dimensions=" + screen.width + "x" + screen.height;
</script>

Con questo codice non facciamo altro che creare un cookie in cui salviamo i dati relativi alle dimensioni dello schermo.

Il secondo passo prevede l'utilizzo di un file PHP, di cui forniamo qui sotto il codice:

<?php
$device_width = 0;
$device_height = 0;
$file = $_SERVER['QUERY_STRING'];
if (file_exists($file)) {
// Read the device viewport dimensions
if (isset($_COOKIE['device_dimensions'])) {
$dimensions = explode('x', $_COOKIE['device_dimensions']);
if (count($dimensions)==2) {
$device_width = intval($dimensions[0]);
$device_height = intval($dimensions[1]);
}
}
if ($device_width > 0) {
$fileext = pathinfo($file, PATHINFO_EXTENSION);
// Low resolution image
if ($device_width <= 800) {
$output_file = substr_replace($file, '-low', -strlen($fileext)-1, 0);
}
// Medium resolution image
else if ($device_width <= 1024) {
$output_file = substr_replace($file, '-med', -strlen($fileext)-1, 0);
}
// check the file exists
if (isset($output_file) && file_exists($output_file)) {
$file = $output_file;
}
}
// return the file;
readfile($file);
}
?>

Tramite PHP leggiamo il contenuto del cookie; a quel punto, a seconda delle dimensioni dello schermo e dei parametri fissati nello script (800, 1024, etc), serviamo all'utente l'immagine giusta.

Potete copiare e incollare il codice in un documento vuoto, da nominare poi 'index.php'. Spostate quindi 'index.php' all'interno della cartella in cui si trovano le immagini.

Le versioni piccola e media delle immagini dovranno seguire delle convenzioni per il nome. Se l'immagine standard, dunque, quella grande, si chiama 'foto.jpg', la versione a bassa risoluzione dovrà essere nominata 'foto-low.jpg', la versione a media risoluzione 'foto-med.jpg'. Non è necessario comunque creare tre versioni dell'immagine, due sono sufficienti.

Per concludere dobbiamo inserire l'immagine nel nostro HTML:

<img src="images/index.php?pini.jpg">
<!-- possiamo anche scrivere: <img src="images/?pini.jpg"> -->

Come si vede, nella src andiamo a puntare al file 'index.php', aggiungendo come query string il rimando all'immagine ad alta risoluzione, quella standard. Sarà lo script a occuparsi del resto, ovvero di servire a ciascun dispositivo l'immagine ottimizzata.

Ecco l'esempio. I dispositivi mobili riceveranno l'immagine 'pini-low.jpg'. Se Javascript non è disponibile, i browser ricevono l'immagine standard.

Nella terza parte dell'articolo esamineremo una soluzione che contempla diversi casi, basata su un piccolo script lato server.

Adaptive Images

La nostra panoramica si conclude con Adaptive Images. Al momento è sicuramente la soluzione più completa ed efficace. Consente infatti di superare alcuni problemi insiti nelle tecniche viste qui sopra.

In entrambi i casi, infatti, in presenza di un sito già esistente e attivo, sarebbe necessario dover riscrivere tutto il markup HTML relativo alle immagini per implementare il tutto! Ancora: è necessario preparare e caricare sul server almeno due versioni differenti di una stessa immagine.

Adaptive Images, invece, lavora con una sola immagine, quella originaria; e non necessita di alcuna riscrittura del markup. Vediamo come funziona nella sua configurazione di base.

I prerequisiti tecnici minimi prevedono un web server Apache 2, la presenza di PHP 5.x e delle librerie GD.

Per prima cosa scarichiamo dal sito ufficiale l'ultima versione del pacchetto e scompattiamolo.

Se nella directory root del nostro sito non c'è un file .htaccess, carichiamo in quella posizione il file .htaccess che troviamo nel pacchetto zip. Se abbiamo già un file .htaccess in quella posizione, dobbiamo invece editarlo.

Apriamolo e verifichiamo se c'è definita questa direttiva:

<IfModule mod_rewrite.c>

Se c'è un blocco che inizia così, allora dobbiamo inserire all'interno del blocco questo codice:

# Adaptive-Images -----------------------------------------------------------------------------------
# Add any directories you wish to omit from the Adaptive-Images process on a new line, as follows:
# RewriteCond %{REQUEST_URI} !some-directory
# RewriteCond %{REQUEST_URI} !another-directory
RewriteCond %{REQUEST_URI} !assets
# Send any GIF, JPG, or PNG request that IS NOT stored inside one of the above directories
# to adaptive-images.php so we can select appropriately sized versions
RewriteRule .(?:jpe?g|gif|png)$ adaptive-images.php
# END Adaptive-Images -------------------------------------------------------------------------------

Se non c'è una sezione che richiama il mod_rewrite, possiamo invece incollare nel nostro file .htaccess tutto il contenuto di quello di Adaptive Images.

Attenzione! C'è una sezione di questo file molto importante. Di default, con questa configurazione facciamo sì che tutte le immagini (JPEG, GIF, PNG) vengano intercettate e ridimensionate. Ma è presumibile che non per tutte le immagini vogliamo che ciò accada! Per proteggere specifiche cartelle, sarà sufficiente creare una lista nel file .htaccess usando questa sintassi:

RewriteCond %{REQUEST_URI} !nome_cartella

Nell'esempio le immagini presenti nella cartella assets non saranno ridimensionate.

Dopo il file .htaccess dobbiamo copiare nella root del sito il file adaptive-images.php.

Sempre nella directory root dobbiamo creare una nuova cartella. Va chiamata 'ai-cache' e deve avere permessi di lettura e scrittura (CHMOD 777).

Sul server abbiamo finito. Non ci rimane che inserire nella sezione head della nostra pagina questa riga di codice Javascript:

<script>document.cookie='resolution='+Math.max(screen.width,screen.height)+'; expires=; path=/';</script>

Il codice crea un cookie che contiene le dimensioni dello schermo. A quel punto, la regola presente nel file .htaccess reindirizza le immagini allo script PHP ('adaptive-images.php'). Se esiste un'immagine conservata nella cache, ci viene servita quella; altrimenti, in base alle dimensioni dello schermo, lo script provvede a generare una versione ridimensionata.

Nel file PHP è presente questa riga:

$resolutions = array(1382,992,768,480,320);

Le cifre rappresentano i cosiddetti breakpoint, ovvero le dimensioni in larghezza (risoluzione in pixel dello schermo) che lo script userà come riferimento per creare le versioni ridimensionate dell'immagine primaria.

Ecco dunque l'esempio. Il markup per l'immagine è questo:

<img src="ny.jpg">

Nessuna query string, niente di niente. Normale HTML per l'inclusione di immagini.

La foto primaria è una JPEG di 1900x1624px pesante 815kb.

Visualizzando la pagina su un iMac 21" con risoluzione monitor di 1920x1080, ci viene servita un'immagine di 1382x1182px pesante 219kb.

Visualizzando il documento su un iPhone 3gs

Figura 5. Visualizzazione su iPhone
Visualizzazione su iPhone

otteniamo un'immagine di 480x411px pesante 83kb. Tutto al volo, senza che sia necessario creare le diverse versioni in anticipo!

Per approfondimenti rimandiamo al sito ufficiale e alla documentazione contenuta nei file di istruzione.

È disponibile per il download un pacchetto zip che contiene tutte le immagini e i file usati nell'articolo, compresi i sorgenti di tutte le tecniche viste.

Ti consigliamo anche