No. 94

Titolo originale: Fluid Images

Pubblicato in: CSS, HTML, Layout & Grids, Responsive Design

Scritto da Ethan Marcotte

Siamo lieti di presentare un estratto dal Capitolo 3 di Responsive Web Design di Ethan Marcotte (A Book Apart, 2011). Questo capitolo segue quello sulle griglie fluide (fluid grids) ed amplia il discorso ivi iniziato con le immagini fluide. -Ed.

Le cose stanno andando bene finora: abbiamo un layout basato su una griglia che non sacrifica la complessità per la flessibilità. Devo ammettere che la prima volta che ho scoperto come creare una griglia fluida ero piuttosto orgoglioso di me stesso!

Fig 3.0: La nostra griglia flessibile è finalmente finita. Non c'è un valore espresso in pixel a perdita d'occhio e non abbiamo dovuto lesinare sull'estetica.

Tutto a un tratto però, come spesso capita nel web design, giunge la disperazione. Al momento, la nostra pagina è piena di parole e poco altro. In realtà, null'altro, non è nient'altro che testo. Perché questo dovrebbe essere un problema? Beh, il testo si riposiziona senza sforzi all'interno di un contenitore flessibile ma, non so se l'avete notato, sembra che Internet abbia una o due di quelle cose chiamate “immagini” sparse qua e là, solo che noi non ne abbiamo incorporata nemmeno una nella nostra griglia flessibile.

Quindi, cosa succede quando introduciamo delle immagini a larghezza fissa nel nostro design flessibile?

Tornare indietro, indietro al markup, markup

Per trovare una risposta a questa domanda, facciamo un esperimento veloce: inseriamo un'immagine direttamente nel nostro modulo blog e vediamo come risponde il layout. La prima cosa che dobbiamo fare è trovarle un posto all'interno del markup.

Vi ricordate il nostro piccolo blockquote, comodamente infilato nell'articolo del blog? Bene, abbiamo fin troppo testo su questa dannata pagina, quindi lo rimpiazziamo con un'immagine inserita nel testo:

 
<div class="figure">
  <p>
    <img src="/robot.jpg" alt="" /> 
    <b class="figcaption">Lo, the robot walks</b>
  </p>
</div>

Nulla di che: un elemento img seguito da una breve caption descrittiva contenuta in un elemento b. In realtà, sto utilizzando i tag figure/figcaption di HTML5 come nomi delle classi in questa snippet, per darle una solida base semantica.

(I lettori più attenti si saranno accorti che sto usando un elemento b come hook non semantico. Ora, alcuni web designer potrebbero utilizzare al suo posto uno span, ma io preferisco la concisione di tag quali b o i per il markup non semantico).

Fatto il markup HTML, assegniamogli delle regole CSS di base:

 
.figure {
  float: right;
  margin-bottom: 0.5em;
  margin-left: 2.53164557%;  /* 12px / 474px */
  width: 48.7341772%;  /* 231px / 474px */
}

Fig 3.1: Un'immagine appropriatamente robotica di un robot, per gentile concessione di Jeremy Noble.

Stiamo qui realizzando un grazioso effetto inset per la nostra figura: sarà spostata sulla destra e occuperà circa la metà della larghezza del nostro articolo o quattro colonne della nostra griglia flessibile. Markup: ok; stile: ok. Ovviamente, tutto questo HTML e CSS è inutile se non c'è un'immagine disponibile.

Ora, dal momento che voglio un bene dell'anima a voi (e ai robot), non poteva andare bene una qualunque immagine. E infatti, dopo aver perlustrato il web per molti minuti, ho trovato un robo-ritratto splendidamente imponente (fig. 3.1). La cosa meravigliosa riguardo questa immagine (a parte il fatto che si tratta di un robot, ovviamente) sta nel suo essere enorme. L'ho leggermente ritagliata, ma non l'ho ridotta in dimensioni, lasciandola alla sua risoluzione originaria di 655x655. Questa immagine è molto più grande di quello che sappiamo che potrebbe essere il suo contenitore flessibile, rendendola un caso perfetto per testare la robustezza e la flessibilità del nostro layout.

Quindi, mettiamo la nostra immagine sovradimensionata sul server, ricarichiamo la pagina e...oh! Ehm... Questa è la cosa più brutta che si possa trovare su internet!

Fig 3.2: La nostra immagine gigante è gigante: il nostro layout è rotto.

In realtà, il risultato non ci stupisce più di tanto. Il nostro layout non è rotto di per sé: il nostro contenitore flessibile funziona bene e le proporzioni delle colonne della nostra griglia sono rimaste intatte. Ma dal momento che la nostra immagine è molto più grande del div .figure che la contiene, la parte in eccesso del contenuto esce dal suo contenitore ed è visibile all'utente. Semplicemente, non ci sono vincoli applicati all'immagine che la mettano in grado di capire che si trova in un ambiente flessibile.

Immagini fluide

Cosa succederebbe se introducessimo tali vincoli? E se potessimo scrivere una regola che impedisca alle immagini di sforare la larghezza dei propri contenitori?

Beh, ecco la buona notizia: è una cosa molto semplice da fare:

 
img {
  max-width: 100%;
}

Scoperta per la prima volta dal web designer Richard Rutter, questa regola ci fornisce immediatamente un vincolo molto comodo per qualsiasi immagine all'interno del nostro documento. Ora, il nostro elemento img verrà visualizzato a qualunque dimensione voglia purché questa sia inferiore a quella del suo elemento contenitore. Ma se succede che l'elemento img sia più grande del suo container, allora la direttiva max-width: 100% forzerà la larghezza dell'immagine alla larghezza del suo contenitore. E, come potete vedere, la nostra immagine è andata a posto.

Fig 3.3: Semplicemente includendo max-width: 100%, abbiamo impedito alla nostra immagine di uscire dal suo contenitore flessibile. Nota a margine: adoro max-width: 100%.

Inoltre, i browser moderni si sono evoluti fino al punto da riuscire a ridimensionare automaticamente le immagini in maniera proporzionale: con il ridimensionamento del nostro contenitore flessibile l'immagine si allarga o si restringe preservando il rapporto altezza-larghezza.

Fig 3.4: Non importa quanto diventi largo o stretto il contenitore flessibile: l'immagine si ridimensionerà in proporzione. Magia? Chi può dirlo!

Spero che non siate già stanchi di tutte queste buone notizie perché, guarda caso, la regola max-width: 100% si può applicare anche alla maggior parte degli elementi di larghezza fissa, come i video o altri rich media. Infatti, possiamo rinforzare il nostro selettore affinché copra altri elementi “media-ready”, in questo modo:

 
img,
embed,
object,
video {
  max-width: 100%;
}

Sia che si tratti di un grazioso video Flash, di un qualche altro embedded media o di una semplice img, i browsers si comportano in maniera imparziale, ridimensionando il contenuto proporzionalmente nel layout flessibile. Il tutto grazie al nostro piccolo vincolo max-width.

Fig 3.5: Altri media vanno d'accordo con max-width: 100%, diventando anch'essi flessibili. Ho già detto che adoro max-width: 100%?

E così abbiamo risolto il problema delle immagini flessibili e degli altri media che si ridimensionano, giusto? Una sola regola CSS e siamo a posto?

Perché questo lavoro non è mai facile

E' ora di iniziare il processo di guarigione: dobbiamo passare attraverso il dolore, le lacrime, la lacerazione delle vesti e parlare di alcune questioni specifiche dei vari browser riguardanti le immagini flessibili.

max-width in Internet Explorer

La dura e spietata verità è che Internet Explorer 6 ed i suoi predecessori non supportano la proprietà max-width. IE7 e successive? Oh, è positivamente traboccante di supporto per max-width. Ma se siete costretti a supportare il (ehm) venerabile IE6 o predecessori, il nostro approccio ha bisogno di alcune rifiniture.

Ora, ci sono molti modi documentati per far sì che max-width funzioni in IE6. La maggior parte di questi sono JavaScript-driven, solitamente basati su un filtro di espressioni proprietarie di Microsoft per valutare dinamicamente la larghezza di un elemento e per ridimensionarlo manualmente se eccede una certa soglia. Per un esempio di questi workaround decisamente non-standard, vi raccomando l'ormai classico blog post di Svend Tofte su questo argomento.

Io? Io tendo a preferire un approccio più lo-fi e CSS-driven. Mi spiego: tutti i browser moderni comprendono il vincolo max-width.

 
img,
embed,
object,
video {
  max-width: 100%;
}

Ma in un foglio di stile separato specifico per IE6, includo la seguente regola:

 
img,
embed,
object,
video {
 width: 100%;
}

Vedete la differenza? IE6 e precedenti comprendono la regola width: 100%, invece che max-width: 100%.

Una parola di avvertimento: siate cauti qui, perché queste sono regole drasticamente differenti. Laddove max-width: 100% dice alle nostre immagini di non superare mai la larghezza dei loro contenitori, width: 100% forza le nostre immagini ad avere sempre la larghezza dei loro elementi contenitori.

Nella maggior parte dei casi questo approccio funzionerà. Ad esempio, possiamo certamente assumere che la nostra immagine sovradimensionata robot.jpg sarà sempre più larga del suo elemento contenitore, pertanto la regola width: 100% funzionerà benissimo.

Ma per immagini più piccole come le thumbnails o come la maggior parte dei video embedded, potrebbe non essere appropriato ingrandirle alla cieca con i CSS. Se questo è il vostro caso, allora potrebbe essere giustificata un po' più di specificità per IE:

 
img.full,
object.full,
.main img,
.main object {
  width: 100%;
}

Se non volete che la regola width: 100% venga applicata a qualunque media di larghezza fissa presente nella vostra pagina, possiamo semplicemente scrivere una lista di selettori che abbia come obiettivo alcuni tipi di immagini o video (img.full), oppure alcune aree nel vostro documento dove sapete che dovrete gestire dei media sovradimensionati (.main img, .main object). Pensate a questo elenco come ad una whitelist: se le immagini o altri media appaiono su questa lista, allora saranno flessibili, altrimenti saranno di dimensioni fisse nel loro tedioso modo orientato al pixel.

Quindi, se state ancora offrendo supporto alle versioni legacy di Internet Explorer, una regola width: 100% applicata con attenzione può far funzionare le immagini flessibili magnificamente. Ecco, abbiamo risolto un bug, ma ce ne rimane un altro.

E ragazzi, è una cosa ancora più bizzarra.

Paragrafo in cui diventa evidente che Windows ci odia

Fig 3.6: Visualizzata qui in IE6, la nostra immagine del robot ha sviluppato degli antiestetici artefatti. Suppongo che a Windows non interessino granché le nostre immagini.

Se guardate il nostro modulo blog con certi browser basati su Windows, la nostra robot.jpg è passata dall'apparire imponente all'apparire, beh, rotta. Ma questa non è tanto una questione dipendente da un browser quanto piuttosto dalla piattaforma: Windows non ridimensiona molto bene le immagini. Infatti, quando vengono ridimensionate tramite CSS, in Windows le immagini sviluppano rapidamente degli artefatti, che influiscono drasticamente sulla loro qualità. E non in maniera positiva.

Per un rapido test case, ho inserito un'immagine piena di testo in un contenitore flessibile e ho ridimensionato l'immagine con la soluzione max-width: 100%, mentre IE6 e precedenti utilizzeranno il workaround width: 100%. Ora, nella realtà non mettereste mai così tanto testo in un'immagine, ma mi serviva un esempio che illustrasse perfettamente quanto possano andare male le cose in IE7 e precedenti. Come potete vedere, l'immagine appare, se mi passate il termine tecnico, proprio orribile.

Ma prima di abbandonare la speranza di avere immagini scalabili e flessibili, vale la pena notare che questo bug non interessa tutti i browser basati su Windows. Infatti, ne sono interessati solo Internet Explorer 7 e precedenti, così come Firefox 2 e precedenti sempre su Windows. I browser più moderni come Safari, Firefox 3+ e IE8+ non mostrano alcun problema con le immagini flessibili. Inoltre, il bug sembra essere stato sistemato in Windows 7. Ecco altre buone notizie!

Fig 3.7: In alcuni browser basati su Windows, l'immagine sviluppa presto troppi artefatti per poter essere leggibile.

Quindi, definito lo “scope” del problema, ci sarà sicuramente una patch che possiamo applicare! Fortunatamente c'è, con l'eccezione di Firefox 2.

Ora, questo vecchio brizzolato browser fu rilasciato nel 2006, quindi penso sia lecito ritenere che non stia esattamente intasando i log del traffico del vostro sito. In ogni caso, una patch per Firefox 2 richiede un browser sniffing veramente intricato che miri a specifiche versioni su specifiche piattaforme e, nel migliore dei casi, il browser-sniffing è inaffidabile. Ma anche se volessimo fare questo tipo di scoperta, queste versioni più vecchie di Firefox non hanno un interruttore che possa sistemare le nostre immagini rovinate.

Tuttavia, Internet Explorer ha tale interruttore. (Perdonatemi, abbasso la cresta per il titolo della sezione successiva)

Ave AlphaImageLoader, eroe conquistatore

Avete mai provato a far funzionare i PNG trasparenti in IE6 e precedenti? Se sì, ci sono buone probabilità che abbiate incontrato AlphaImageLoader, uno dei filtri CSS proprietari di Microsoft. Nel tempo sono state create delle robuste patch per colmare la mancanza di supporto di IE per l'alpha channel dei PNG (la libreria DD_belatedPNG di Drew Diller è al momento una delle mie preferite), ma storicamente, se avevate un PNG come background di un elemento, potevate mettere la regola seguente in un foglio di stile specifico per IE: (gli “a capo” sono segnati con », Ed.)

 
.logo {
  background: none;
  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader»
  (src="/path/to/logo.png", sizingMethod="scale");
}

La patch AlphaImageLoader fa alcune cose. Innanzitutto, rimuove l'immagine di background dall'elemento, poi la inserisce nell'oggetto AlphaImageLoader che sta “tra” l'effettivo layer di background ed il contenuto dell'elemento. Ma la proprietà sizingMethod è la vera trovata: impone all'oggetto AlphaImageLoader di tagliare qualunque parte dell'immagine che fuoriesca dal suo container, di trattarla come un'immagine regolare, o ridimensionarla per farla stare all'interno del suo elemento contenitore.

Vi sento sbadigliare: cosa può mai avere a che fare uno specifico IE fix per PNG con la resa disastrata della nostra immagine?

C'entra un bel po', come vi vado a dimostrare. Ad un certo punto ho scoperto che applicare AlphaImageLoader ad un'immagine ne migliora drasticamente la resa in IE, portandolo al livello di, beh, qualunque altro browser sul pianeta. Inoltre, impostando la proprietà sizingMethod a scale, possiamo usare il nostro oggetto AlphaImageLoader per creare l'illusione che l'immagine sia flessibile.

Ecco quindi che improvviso un po' di JavaScript per automatizzare il processo: scaricate lo script ed includetelo semplicemente in ogni pagina che abbia delle immagini flessibili. Questo analizzerà il vostro documento per creare una serie di oggetti AlphaImageLoader flessibili e di alta qualità.

E con tale fix applicato, la differenza nella resa delle nostre immagini è notevole: nel nostro esempio siamo passati da un'immagine distorta in maniera impossibile ad una resa immacolata. E funziona perfettamente in un contesto flessibile!

Fig 3.8: La nostra immagine è ora perfettamente leggibile e si ridimensiona magnificamente. Un pizzico di AlphaImageLoader e tutto passa!

(Occorre ricordare che molti filtri proprietari di Microsoft, ed in particolare AlphaImageLoader, aggiungono un overhead alla performance. Stoyan Stefanov copre in dettaglio le insidie nello YUI blog. Cosa significa questo? Assicuratevi di testare il fix su tutto il vostro sito, valutarne l'effetto sui vostri utenti e stabilire se vale la pena migliorare il rendering a scapito della performance.

Con il fix max-width: 100% al suo posto (e supportato dalle nostre patch width: 100% e AlphaImageLoader), la nostra immagine inserita nel testo si ridimensiona molto bene su tutti i nostri target browser. Non importa la dimensione della finestra del browser, la nostra immagine si ridimensiona in maniera armonica con le proporzioni della nostra griglia flessibile.

E le immagini che non sono nel nostro markup?

Rendere flessibili le immagini “tiled” di background

Supponiamo che il nostro caro e stimato designer ci abbia mandato una revisione del mockup del nostro modulo blog. Notate qualche differenza?

Fig 3.9: La sidebar del nostro blog adesso sfoggia una grafica di background. Forte!

Fino ad ora, il contenuto del nostro blog aveva uno sfondo piuttosto modesto, quasi bianco. Ma adesso il design è stato leggermente modificato, con l'aggiunta di un background a due colori per la blog entry, così da avere un maggiore contrasto tra la colonna di sinistra e quella di destra. Inoltre, c'è un sottile livello di rumore aggiunto al background che dà una ulteriore texture al nostro design:

Fig 3.10: Un dettaglio del nostro nuovo background.

Quindi, come facciamo ad aggiungere questa nuova immagine di background al nostro template?

Nel lontano 2004, Dan Cederholm scrisse un articolo geniale che dimostrava come una immagine di background ripetuta verticalmente potesse essere usata per creare l'illusione di una “falsa colonna”. La genialità di questa tecnica sta nella sua semplicità: allineando verticalmente un'immagine di background a colori dietro al nostro contenuto, possiamo creare l'illusione di colonne di uguale altezza.

Nella tecnica originale di Dan, l'immagine di background veniva semplicemente centrata in cima all'area del contenuto e poi ripetuta verticalmente, in questo modo:

 
.blog {
  background: #F8F5F2 url("blog-bg.png") repeat-y 50% 0;
}

E questa tecnica funziona benissimo. Ma la tecnica di Dan presume che il vostro design sia a larghezza fissa, così da poter creare un'immagine che coincida con la larghezza del vostro design. Allora, di grazia, come dovremmo infilare un'immagine di sfondo che si ripeta su due colonne flessibili?

Grazie ad alcune antesignane ricerche del designer Doug Bowman, possiamo ancora applicare la tecnica delle false colonne. Serve giusto un po' di pianificazione extra così come una spruzzata della nostra formula preferita: obiettivo ÷ contesto = risultato.

Per prima cosa, cominceremo con l'osservare il nostro mockup per trovare il punto di transizione nella nostra immagine di background: il pixel esatto in cui la nostra colonna passa dal bianco al grigio. E per come stanno le cose, questa transizione avviene al pixel 568.

Fig 3.11: La nostra colonna bianca cambia in grigio al pixel 568. Questo è il nostro punto di transizione.

Armati di questa informazione, possiamo adesso modificare l'approccio delle “false colonne” alla nostra griglia fluida. Per prima cosa, convertiamo il punto di transizione in un valore basato su una percentuale relativo alla larghezza del nostro modulo blog. E per fare questo rientra di nuovo in gioco la nostra formula obiettivo ÷ contesto = risultato. Abbiamo il nostro valore obiettivo, 568px e la larghezza del design, il nostro contesto, è 900px. E se inseriamo questi due valori nella nostra robusta formula, otteniamo:

568 ÷ 900 = 0.631111111111111

Esatto, un altro numero impossibilmente lungo, che, convertito in percentuale dà 63.1111111111111%.

Tenete a mente questa percentuale per un attimo. Ora, apriamo il nostro editor di immagini preferito e creiamo un documento dalla grandezza esagerata, ad esempio, da 3000 pixel di larghezza. E dal momento che ripeteremo questa immagine verticalmente, la sua altezza sarà di soli 160px.

Fig 3.12: Un canvas mostruosamente largo che (a breve) faremo diventare la nostra immagine di background.

Tra un attimo trasformeremo questo documento vuoto nella nostra immagine di background. Ma perché è così largo? Beh, questa immagine deve essere più larga di quanto possiamo ragionevolmente presumere che sarà mai larga una finestra del browser. E a meno che stiate leggendo questo testo da un monitor del XXV secolo della dimensione di una parete fatto da... che so... ologrammi o qualcosa così, presumo che il vostro monitor non sia così largo.

Per creare le colonne, dobbiamo applicare la percentuale del punto di transizione (63.1111111111111%) al nostro nuovo e più ampio canvas. Così, se stiamo lavorando con una immagine larga 3000px dovremo solo moltiplicare questa larghezza per la percentuale, in questo modo:

3000 x 0.631111111111111 = 1893.333333333333

Come risultato otteniamo 1893.333333333333. E siccome Photoshop non gestisce nulla che non sia un pixel intero, lo arrotondiamo a 1893 pixel. Armati di questo numero, ricreiamo la texture nella nostra immagine vuoata, passando dal bianco al grigio al pixel 1893.

Fig 3.13: Abbiamo applicato la percentuale alla nostra “oh così grande!” immagine di background, creando le nostre colonne pronte per essere ripetute.

In che modo tutto ciò ci è d'aiuto? Beh, tutto quello che abbiamo appena fatto consiste nel ridimensionare proporzionalmente il nostro punto di transizione per arrivare fino a questo nuovo, e più largo, canvas. Così possiamo prendere il nuovo valore del pixel ed usarlo per creare le nostre colonne: la colonna bianca sarà larga 1893px, mentre la colonna grigia riempirà quello che resta.

Adesso ci rimane solo una cosa da fare: inserire la nostra nuovissima immagine nel foglio di stile.

 
.blog {
  background: #F8F5F2 url("blog-bg.png") repeat-y 63.1111111111111% 0;  
  /* 568px / 900px */
}

Così come nella tecnica originale di Dan, abbiamo posizionato di nuovo l'immagine al top del nostro blog e poi abbiamo impostato la ripetizione verticale verso il basso (repeat-y). Ma il valore di background-position riutilizza la percentuale del punto di transizione (63.1111111111111% 0), facendo rimanere le colonne al loro posto al ridimensionarsi del nostro design.

E con ciò, abbiamo delle false colonne che funzionano benissimo in un layout fluido. Il tutto grazie all'approccio originale di Dan Cederholm, potenziato con un po' di “pensiero proporzionale”.

Fig 3.14: Le nostre false colonne flessibili.

Immagini di background totalmente flessibili?

Ovviamente le nostre false colonne non sono veramente flessibili: stiamo semplicemente utilizzando le percentuali per posizionare l'immagine di background in maniera da far sembrare che le colonne si ridimensioni con il loro contenitore. Le dimensioni dell'immagine non sono affatto cambiate.

Ma cosa succede con un'immagine di background che in effetti deve proprio ridimensionarsi assieme al layout? Ad esempio, potreste aver messo un logo come background di un elemento h1, o utilizzato le sprites per creare dei rollovers per la navigazione del vostro sito. Possiamo ridimensionare le immagini che devono vivere nel background?

In un certo senso. C'è una proprietà CSS3 chiamata background-size che potrebbe permetterci di creare delle immagini veramente flessibili, ma, l'avrete già capito, il suo supporto da parte dei browser è piuttosto immaturo.

Nel frattempo, ci sono alcune soluzioni piuttosto ingegnose basate su JavaScript: ad esempio, il jQuery plugin Backstretch di Scott Robbin simula immagini di background dell'elemento body ridimensionabili. E, come vedrete nel prossimo capitolo, le CSS3 media query potrebbero essere usate per applicare diverse immagini di background create ad hoc per differenti range di risoluzione. Quindi, sebbene il background-size non sia ancora utilizzabili, come si suol dire, il cielo è il limite.

Share/Save/Bookmark
 

Discutiamone

Ti sembra interessante? Scrivi tu il primo commento


Cenni sull'autore

Ethan Marcotte

Ethan MarcotteEthan Marcotte è un web designer & developer che ha molto a cuore il design ben fatto, il codice elegante e l'intersezione dei due. Nel corso degli anni, Ethan ha potuto lavorare con clienti quali il Sundance Film Festival, la Stanford University, il New York Magazine e The Today Show. Dice molte parolacce su Twitter e da grande vorrebbe essere un robot ninja che non si ferma mai.