No. 97

È nostro compito, in qualità di designer e developer, scegliere anche il più apparentemente semplice task e cercare dei modi per migliorarlo . Quando Ethan Marcotte ha coniato l'espressione “responsive web design,”, ha detto che un sito web responsive è composto da tre elementi: una griglia flessibile (flexible grid), delle immagini e dei media flessibili e le media query. Facendo così, ha aperto un mondo di nuove ed eccitanti componenti con cui ossessionarci. Io ho scelto le immagini flessibili.

È piuttosto semplice dare uno stile alle immagini per far sì che si ridimensionino fino alla dimensione dell'elemento padre aggiungendo img {mag-width: 100%;} al foglio di stile. Per usarlo in maniera efficace, tuttavia, l'immagine deve essere sufficientemente larga per ridimensionarsi a qualunque dimensione possiamo ragionevolmente aspettarci sul più grande display possibile. Questo implica una gran quantità di overhead. Nel caso migliore è semplicemente uno spreco. Nel caso peggiore, il mobile browser si mette le mani in tasca e si mette in un angolo, di cattivo umore, praticamente non rendendo la pagina. Un pugno di immagini stampate a vivo progettate per un display da 13" potrebbe mettere in ginocchio un dispositivo mobile su una connessione Edge.

Sfortunatamente, non possiamo testare la larghezza di banda in nessun modo affidabile, non adesso perlomeno. Fare dei test implicherebbe probabilmente l'introduzione di un significativo download da sottoporre a misurazione, che è molto simile a dar fuoco a qualcosa per capire esattamente quanto sia infiammabile. Quello che possiamo determinare con un buon grado di affidabilità è la dimensione dello schermo del device e sebbene non possiamo necessariamente usare la dimensione dello schermo per fare assunzioni riguardanti la larghezza di banda, si collega direttamente a quello che stiamo cercando di ottenere: sebbene la dimensione della finestra del browser possa cambiare, non avremo mai bisogno di immagini più grandi dello schermo dell'utente.

Mentre stavamo lavorando al nuovo sito del Boston Globe, abbiamo inventato una tecnica per attenuare la dimensione delle richieste per gli utenti che hanno una larghezza di banda limitata. Prima di descriverla, devo avvisarvi: non ha funzionato. Ma era tutto programmato.

Come funzionavano le immagini responsive

Scott Jehl ha creato in maniera brillante la tecnica delle “immagini responsive” di Filament Group. Siamo partiti dall'ipotesi che la tecnica dovrebbe garantire il risultato per i device mobili. Con un approccio mobile-first, se una qualunque delle parti del processo fallisce, l'utente dovrebbe essere ancora in grado di ricevere un'immagine rappresentativa, seppur più piccola, ed evitare le richieste inutilmente grandi su un device che potrebbe avere una larghezza di banda limitata. Il progressive enhancement vince.

Ci sono tre componenti chiave per lo script delle nostre immagini responsive: il markup, il JavaScript ed una regola di redirect server-side.

Probabilmente non vi sorprenderà sapere che abbiamo cominciato con un tag immagine:

<img src="/mobile-size.gif">

Con questo come base, stiamo garantendo che il default è un'immagine della dimensione adatta al mobile. Mettiamo il percorso per l'immagine più grande in un attributo data per accedervi facilmente con JS:

<img src="/images/mobile-size.jpg" data-fullsrc="/images/desktop-size.jpg">

Adesso che entrambe le sorgenti delle immagini sono nel nostro markup, abbiamo bisogno di un modo per caricare in maniera condizionata la sorgente appropriata. Per farlo abbiamo bisogno di conoscere la dimensione dello schermo dell'utente. Fortunatamente, c'è un modo relativamente semplice per determinare la dimensione dello schermo attraverso JavaScript usando una property nell'oggetto window nel browser: window.screen.width, sebbene anche questa non sia totalmente affidabile.

Qui incappiamo in una grande sfida: dobbiamo comunicare questa dimensione al server in tempo per rinviare la richiesta per l'originale src dell'immagine, se necessario. Il server ha bisogno di sapere la dimensione dello schermo del client prima che le nostre immagini vengano visualizzate.

Alla fine abbiamo deciso di impostare la dimensione dello schermo in un cookie. Un cookie impostato nella head di un documento risulta pronto in tempo per il parsing del body del documento ed include le richieste delle immagini.

Presumo che stiate rabbrividendo all'idea di una funzionalità dipendente da un cookie e lo capisco. Alcune delle nostre prime iterazioni includevano i tag <noscript e document.write. Ho ancora gli incubi sui tag base inclusi dinamicamente. Quelli erano tempi duri e le avevamo provate tutte.

Il nostro secondo task JavaScript era ben più semplice: se lo schermo ha una dimensione superiore a quella specificata, scambiamo l'originale src di img con il percorso contenuto nell'attributo data-fullsrc e visualizziamo l'immagine più grande al posto di quella più piccola.

Dal momento che la dimensione dello schermo è adesso disponibile sul server, giocherelliamo con una soluzione che ridimensiona automaticamente l'immagine originale per adattarla allo schermo. Abbiamo deciso di non adottare questa soluzione per svariati motivi:

  • Volevamo tenere al minimo assoluto la dipendenza server-side ed implementare solo qualcosa che potesse essere facilmente ricreato in vari ambienti server.
  • Piuttosto che ridimensionare semplicemente un'immagine esistente, abbiamo pensato che fosse più importante avere la flessibilità di ritagliare e fare zoom sull'immagine più grande in maniera da renderla ottimizzata completamente per il display su uno schermo più piccolo.
  • Tutte le soluzioni back-end che abbiamo sperimentato implicavano il rimpicciolimento di una grande immagine fino a che questa raggiungeva la dimensione dello schermo, cosa che ci ha fatto venire i brividi. Se la larghezza dello schermo veniva riportata in modo errato o se lo script di front-end avesse fallito, avremmo corso il rischio di sovraccaricare gli utenti con un download enorme ed inutile.

La parte di scambio del src con JavaScript fa la parte del leone del lavoro, ma i dispositivi con schermi più grandi fanno ancora richieste ridondanti, prima per l'immagine mobile, poi l'immagine a dimensione intera. Questo risulta in un effetto visivo piuttosto stridente: l'immagine più piccola potrebbe essere visibile prima che quella più grande prenda il suo posto. Dal momento che il src originale è caricato quando il browser fa il parsing del tag img, non possiamo evitare quella richiesta lato client. Quello che possiamo fare è mitigare queste richieste lato server.

Abbiamo scritto alcune semplici regole rewrite di Apache per intercettare le richieste di immagini e controllare il cookie che avevamo impostato in precedenza. Se si verificano le condizioni del punto di rottura che avevamo specificato, avremmo ridiretto la richiesta per l'immagine di dimensione per il mobile ad una spacer gif 1x1. Questo mantiene bassa la dimensione delle richieste ridondanti, specialmente una volta che sono state messe in cache dal browser e che viene impedito alle immagini la cui dimensione è adatta al mobile di mostrarsi prima di scambiarla con l'immagine a dimensione intera. Dal momento che non vogliamo applicare questa logica ad ogni immagine in tutto il sito, abbiamo poi introdotto una seconda regola che ci permette di contrassegnare le immagini responsive: la logica di cui sopra si manifesta solo se il nome del file dell'immagine continere “.r”.

<img src="/images/mobile-size.r.jpg" data-fullsrc="/images/desktop-size.jpg">

Grazie al nostro approccio mobile-first, avevamo una nostra piccola tecnica preparata piuttosto alla meglio. Se una qualunque delle parti dell'equazione fallisce, nessun utente viene penalizzato dal proprio contesto. Un fallimento lato client, se i cookie o il JavaScript non sono disponibili, risulterà ad esempio in un'immagine più piccola ma perfettamente rappresentativa. Un fallimento lato server implicherebbe una richiesta di un'immagine più piccola prima dell'immagine a dimensione intera, ma in un contesto in cui possiamo almeno assumere una banda maggiore. Nessuno rimarrà senza immagini indipendentemente dal proprio dispositivo, browser e caratteristiche.

Questa è davvero una casualità, dal momento che entro un mese circa dal lancio di BostonGlobe.com l'approccio con le immagini responsive è fallito.

Cosa non ha funzionato

Molti dei browser più nuovi hanno implementato una feature di “image prefetching” che permette alle immagini di essere caricate prima del parsing del body del documento. Nonostante questo metodo di caricamento sia più rapido, questo va contro il nostro obiettivo. Per i nostri scopi, questa caratteristica invalida anche tutti i nostri metodi per comunicare la dimensione dello schermo al server prima che le immagini siano caricate e spezza il nostro meccanismo di redirect lato server. Potete verificarlo proprio adesso su BostonGlobe.com: senza quel redirect vedrete per un breve momento l'immagine della dimensione del mobile prima che venga caricata l'immagine a dimensione intera, ma potrebbe volerci una vista acuta e un po' di refresh di alcune pagine. Fortunatamente, questo overhead aggiuntivo si verifica solo nei desktop browser, dove la larghezza di banda è solitamente un pensiero minore.

Quindi, adesso che si fa?

Un po' di tempo dopo il lancio del sito del Boston Globe, abbiamo continuato a ripetere il nostro approccio. Jason Grigsby ha fatto un incredibile lavoro documentando i dettagli di quelle prove e tribolazioni in una serie di blog post.

Questo ci porta al giorno d'oggi, con alcune delle menti migliori del web che cercano qualcosa, qualunque cosa, che funzioni. Alcuni pensano che sia un problema irrisolvibile al momento e stanno piazzando le loro scommesse sullo user agent detection come soluzione temporanea. Sebbene questa sia una strada perfettamente percorribile nel breve periodo, io sostengo che sia insostenibile andando avanti: con il range in continua espansione di telefoni e tablet in circolazione, non possiamo sperare di mantenere una lista ragionevole di browser e dispositivi per molto tempo.

Credo che la soluzione definitiva non dovrebbe dipendere da script o da CSS, e sicuramente su nulla che abbia a che fare con UA detection, cookie, script personalizzati nel front end o qualunque altra bravata server-side. Il nostro scopo è quello di rappresentare e mandare il contenuto in maniera appropriata e per questo motivo credo che andrebbe risolto nel markup.

Tuttavia, il tag img non è adatto a questo scopo. È efficace nel comunicare le divertenti stranezze dei gatti di casa, ma non è adatto alla logica complessa. Fa una sola cosa e la fa bene: prende una singola sorgente di immagine e la mette sullo schermo. Se dovessimo modificare questo comportamento a livello del browser, non saremmo mai in grado di garantire che i nostri cambiamenti non introducano problemi nei browser più vecchi. Per esperienza, sappiamo anche che img non lascia molto spazio (ammesso che ne lasci) per utilizzare dei polyfill per questo nuovo comportamento.

Quello di cui abbiamo bisogno è un nuovo pattern di markup, uno che ci permetta di specificare più file sorgente, ma che specifichi ancora il markup universalmente riconosciuto come “contenuto di fallback” per i browser che non riconoscono il nuovo tag. Questo dovrebbe risultarvi familiare visto che un tale pattern esiste già: i tag video e audio.

Sappiamo che un tag video contiene dei riferimenti a sorgenti multiple e che possiamo specificare un contenuto di fallback all'interno del tag che sia visibile solo nei browser che non supportano video nativamente, solitamente si tratta di un video basato su Flash. Quello che potreste non sapere è che c'è già un modo per usare le media query per determinare quale sorgente video utilizzare, sebbene il supporto da parte dei browser sia piuttosto irregolare.


<video>
<source src="/high-res.webm" media="min-width:800px" />
<source src="/low-res.webm" />
<img src="/poster.jpg" />
</video>

Da qui, non ci vuole troppa immaginazione per vedere come possiamo usare un pattern come questo.


<picture>
<source src="/high-res.jpg" media="min-width: 800px" />
<source src="/mobile.jpg" />
<!-- Fallback content: -->
<img src="/mobile.jpg" />

</picture>

Potremmo avere un numero illimitato di opzioni usando le source media query: le immagini ad alta risoluzione per i display ad alta risoluzione superiori ad una certa dimensione, ad esempio. Potremmo determinare in maniera affidabile la velocità di connessione, un giorno potremmo addirittura essere in grado di aggiungere media="connection-speed: edge" o media="min-speed: 200kbps" ai nostri elementi sorgente. Se questi elementi sorgente sono implementati come da specifica HTML5, verrà mandata una sola richiesta per quelli che combaciano con la nostra media query. Quello che otteniamo è una singola richiesta su misura, con una flessibilità condizionale limitata solo da una lista di media query in continua espansione.

Una volta che abbiamo stabilito che il markup è la nostra base, potremmo essere in grado di utilizzare dei polyfill per il comportamento atteso nei browser che ancora non lo supportano. Se da una parte è probabile che i polyfill implichino ancora più di una richiesta, cominciare con un pattern di fallback testato e provato ci permette di applicare i polyfill a nostra discrezione.

Già che ci siamo, vorrei un pony

Per come stanno le cose in questo momento, un certo numero di sviluppatori, me compreso, stanno dialogando con WHATWG e con vari team dei browser riguardo i dettagli di questo nuovo elemento. Un gruppo frustrato di sviluppatori che pretende un nuovo elemento non è sicuramente niente di nuovo. Non siamo i primi e sono sicuro che non saremo gli ultimi. Infatti non siamo nemmeno i primi a raggiungere la stessa identica conclusione sull'invio delle immagini: dopo un po' di brainstorming abbiamo appreso che una soluzione molto simile alla nostra è stata postata nella mailing list pubblica del W3C nel Luglio del 2007, simile perfino nella semantica. Questo argomento è stato sollevato più volte nelle liste di discussione del WHATWG e del W3C ed è morto silenziosamente ogni volta, ma mai durante un cambiamento così radicale nel contesto del browsing come quello che stiamo vivendo da circa un anno a questa parte e mai in un contesto così esaltante come il responsive web design.

Sebbene non possiamo garantire che un elemento picture o qualcosa di simile, semantica a parte, vedrà mai la luce del giorno, abbiamo riconosciuto che c'è bisogno di un tale pattern di markup al momento e che un tale approccio ha un enorme potenziale nel futuro. Mi piacerebbe sapere cosa ne pensate voi.

Illustrazioni: Carlo Brigatti

Share/Save/Bookmark
 

Discutiamone

Ti sembra interessante? Scrivi tu il primo commento


Cenni sull'autore

Mat Marquis

Mat “Wilto” Marquis per vivere scrive codice in Filament Group a Boston e distrugge gratuitamente la sua moto sulle strade di North Cambridge. Mat è Chair del Responsive Images Community Group, technical editor di A List Apart ed è stato membro del team di jQuery Mobile. Mat ha finito, seppur con qualche difficoltà, Mega Man 2 senza perdere nemmeno una vita. Mentre state leggendo la sua bio, sta probabilmente perdendo la testa per qualcosa su Twitter.