Web Design Trails - Sulla scia del web design

Responsive images: come rendere flessibili le immagini con PHP

0 php immagini flessibili responsive images

Come abbiamo avuto modo di vedere una delle basi del responsive web design sono le così dette immagini flessibili. Questa tecnica consente nell’adattare la larghezza delle immagini alla risoluzione dello schermo. Oggi vedremo come realizzarla, utilizzando un mix di CSS, Javacript e PHP.

Il CSS base e i problemi di performance

Fare in modo che un’immagine diventi flessibile è in realtà molto semplice. Basta infatti una “normale” regola CSS:

figure img {
	max-width: 100%;
	height: auto;
}

Applicando queste due proprietà otteniamo che l’immagine prende automaticamente la larghezza del contenitore e il browser provvede di ridimensionarne l’altezza, mantenendo le proporzioni.

Tutto finito?! Purtroppo no, perché questo approccio presenta due problemi fondamentali. Il primo è che non sempre con questo metodo si ottiene una qualità accettabile; spesso anzi si ha una notevole perdita di nitidezza rispetto alle versioni che possiamo facilmente ottenere con un editor come Photoshop.

Inoltre, lasciare che il browser si occupi del ridimensionamento implica fornirgli sempre la stessa immagine indipendentemente dalle dimensioni a cui verrà visualizzata; questo significa che uno smartphone riceverà le immagini pensate per il desktop, che hanno una risoluzione e un peso decisamente eccessivo.

Un pizzico di Javascript e una manciata di PHP

Per migliorare la qualità e ridurre la quantità di dati trasferiti, è preferibile che sia il server ad occuparsi di ridimensionare le immagini. Tuttavia, a livello prestazionale, non è il caso che l’elaborazione venga effettuata ad ogni richiesta. Una buon compromesso è fare in modo che il server gestisca una serie di immagini a risoluzione intermedia e fornisca di volta in volta quella più vicina alle dimensioni del dispositivo client.

Occorre però per prima cosa scoprire qual’è la risoluzione a cui il sito viene visualizzato. Il modo più semplice per farlo è ricorrere a un cookie, impostato da javascript durante il caricamento della pagina:

document.cookie = 'screen_resolution=' + 
        Math.max( getWindowWidth(), getWindowHeight() ) + '; path=/';

In questo esempio facciamo riferimento alle dimensioni della finestra del browser ma in un caso reale si può più semplicemente misurare la risoluzione dello schermo, in quanto un utente normalmente non varia la dimensione della finestra del proprio browser (cosa che invece è molto utile fare in fase di sviluppo e test).

A questo punto possiamo concentrarci sulla codifica PHP; creiamo il file image.php che si occuperà di fornire al browser l’immagine alla risoluzione più opportuna. Prima di tutto stabiliamo quante e quali saranno le dimensioni delle versioni gestite dallo script:

// Risoluzioni delle varie immagini da creare
$resolutions = array( 320, 480, 768, 960, 1024, 1200 );

Come si vede dal blocco di codice, in questo esempio prendiamo in considerazione tutte le principali risoluzioni dei dispositivi in circolazione; tuttavia è possibile scegliere a piacimento quante e quali dimensioni gestire.

A questo punto procediamo leggendo il cookie contenuto nella richiesta e determinando quale immagine fornire al client:

// Controllo la presenza del cookie per la risoluzione dello schermo. Se non è presente utilizzo l'immagine originale
if( isset( $_COOKIE[ 'screen_resolution' ] ) ) {
	$screen = $_COOKIE[ 'screen_resolution' ];
} else {
	$screen = $image_width;
}

// Stabilisco la risoluzione dell'immagine che devo fornire al browser
array_push( $resolutions, $image_width );
sort( $resolutions );
foreach( $resolutions as $res ) {
	if( $screen <= $res ) {
		break;
	}
}

Nel caso in cui il cookie non fosse settato (per assenza di javascript o impostazioni di privacy restrittive) l’algoritmo fa in modo di utilizzare le immagini a dimensione piena; così, pur non avendo miglioramenti, otteniamo comunque il comportamento che avevamo in precedenza.

Una volta stabilito quale immagine utilizzare, dobbiamo crearla se non esiste già o non è aggiornata:

$fileToSend = substr_replace( $file, '-' . $res, - strlen( pathinfo( $file, PATHINFO_EXTENSION ) ) - 1, 0 );
// Se l'immagine da fornire non esiste o non è aggiornata la creo al volo
if( !file_exists( $fileToSend ) || filemtime( $file ) >= filemtime( $fileToSend ) ) {
	create_resized_image( $file, $fileToSend, $image_type, $res, round( $res / $ratio ), $image_width, $image_height );
} 

Le versioni alternative avranno la dimensione come suffisso; cioè, se l’immagine originale si chiama vista-new-york.jpg quella per la risoluzione 768 si chiamerà vista-new-york-768.jpg. Il fatto di controllare che l’immagine esiste prima di crearla ci consente anche di differenziare le immagini per ogni risoluzione; in questo modo, se fosse necessario, abbiamo la possibilità di creare “manualmente” dei contenuti alternativi più di impatto per i tablet e gli smartphone.

Lo script a questo punto è quasi completo. Resta solo da generare un etag per agevolare il caching da parte del browser e inviare il risultato della nostra elaborazione.

// Calcolo l'etag per il caching basandomi sulla dimensione e sull'ultima modifica del file originale aggiungendo però la risoluzione specifica
$etag = filesize( $file ) . '-' . filemtime( $file ) . '-' . $res;
header( 'Etag: "' . $etag . '"' );

// Controllo l'etag fornito dal browser
if( !empty( $_SERVER[ 'HTTP_IF_NONE_MATCH' ] ) && $_SERVER[ 'HTTP_IF_NONE_MATCH' ] == $etag ) {
	// Se coicidono l'immagine è aggiornata e non la rimadno
	header('HTTP/1.0 304 Not Modified');
	header('Content-Length: 0');
	exit;
} else {
	// Altrimenti invio l'immagine
	header('Content-type: ' . image_type_to_mime_type( $image_type ) );
	readfile( $fileToSend );
}

L’etag può essere calcolato in vari modi. In questo esempio ho utilizzato la dimensione e la data di modifica del file originale e la risoluzione a cui è adattato. In questo modo variando la larghezza della finestra e ricaricando si otterrà l’immagine aggiornata.

Il tocco finale

Il nostro script è già funzionante. Tuttavia per migliorare i nomi delle immagini in chiave SEO è opportuno riscrivere gli indirizzi.

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_URI} !images-assets
  RewriteRule images/(.*)$ image.php?f=$1
</IfModule>

Con questo script .htaccess per Apache facciamo in modo che tutti gli indirizzi del tipo images/nomeimmagine.jpg vengano riscritti come images.php?f=nomeimmagine.jpg. I file reali dovranno tuttavia risiedere nella cartella images-assets che è esclusa dalla riscrittura.

Conclusioni

Con questo abbiamo ottenuto ciò che volevamo. Le immagini vengono fornite ad una risoluzione adeguata al dispositivo client e questo migliora sia i tempi di caricamento che la qualità. Uno svantaggio è che dobbiamo ricorre a javascript per far funzionare il tutto.

Realizzando questo script abbiamo esaminato un possibile metodo di implementazione di questa tecnica; tuttavia, ci sono ancora molti accorgimenti che occorre studiare per migliorare le prestazione e la robustezza dello script e renderlo pronto ad un utilizzo “sul campo”.

Quando possibile, è probabilmente meglio affidarsi a soluzioni come Adaptive Images, che si basano su questo approccio ma ci forniscono pacchetti già pronti per essere usati nei nostri progetti.

Infine, se si utilizza un CMS può essere una buona pratica affidarsi agli strumenti che esso mette a disposizione per generare le varie versioni dell’immagine durante il caricamento piuttosto che a posteriori.

Lascia un nuovo commento

Ti è piaciuto questo articolo?

Condividilo su Facebook o Twitter!

Chiudi
Se il download non parte, clicca qui