Questa è la traduzione dell'articolo Accessible Data Visualization with Web Standards di Wilson Miner pubblicato originariamente su A List Apart l'8 Aprile 2008. La traduzione viene qui presentata con il consenso dell'editore e dell'autore.
Parliamo di Web 2.0 da così tanto tempo che è ormai passato di moda cercare di specificare cosa significa e cosa non significa. Una cosa è però sicura: ci sono oggi sul web tonnellate di dati. Come web designer stiamo in effetti sempre più lavorando su siti basati su dati.
Anche sul versante della visualizzazione di questi dati non mancano le opzioni. Google ha di recente annunciato le sue Charts API. Sono un grande esempio, ma ci sono anche grandi esempi di strumenti e servizi per creare grafici come immagini e per realizzare visualizzazioni di dati interattive in Flash.
Ci sono anche grandi tecniche basate sull'uso degli standard web, come i CSS bar graphs di Eric Meyer, una tecnica che trasforma il markup pulito e semantico di una tabella in grafici.
Sono tutte opzioni estremamente utili nei casi in cui tutto quello che ci serve è un semplice grafico o un diagramma. Ma cosa ci servirebbe se volessimo includere la visualizzazione di dati come parte integrante del sito e non come una semplice figura isolata o un grafico interattivo? Quando si creano interfacce per esplorare siti centrati su dati, è una buona cosa essere in grado di creare elementi di navigazione che siano anche strumenti di visualizzazione. Possiamo tenere informato l'utente mentre esplora le pagine, in modo che possa prendere decisioni rispetto alle informazioni che gli si presentano davanti.
Potremmo costruire quel tipo di navigazione con Flash, oppure generare immagini statiche ogni volta che i dati cambiano, ma sarebbe un grosso svantaggio in termini di accessibilità e mantenibilità.
Anche operare con markup basato sui web standard ha degli svantaggi. Se vogliamo solo mostrare i dati, possiamo ottenere la ricchezza più semantica e gli agganci in termini di accessibilità con una tabella. Ma quando vogliamo realizzare un sistema di navigazione, allora le tabelle non vanno più bene. Quello di cui abbiamo bisogno è qualcosa che sia a metà: un markup che sia appropriato per la navigazione, ma con degli agganci extra per la semantica e la struttura.
Nell'articolo mi occuperò di presentare tre tecniche di base per incorporare delle semplici visualizzazioni di dati nel contesto di sistemi di navigazione basati sui web standard. Tutti gli esempi iniziano con il mattone fondamentale per creare una navigazione: una lista non ordinata di link.
Lavoreremo un po' sul markup per adattarlo, aggiungeremo dei punti per i dati e un po' di agganci strutturali per lo stile, ma in ogni caso lo schema di base sarà a voi tutti familiare.
Dal momento che non possiamo affidarci alla semantica di una tabella, useremo nomi di classe semantici, un po' come avviene nei microformati, per preservare il più possibile la struttura dei dati nel nostro markup. E poiché useremo HTML e CSS, possiamo usare misure in em
per essere sicuri che i grafici si adattino nel momento in cui si dovesse ridimensionare il testo.
Grafici a barre orizzontali
Questa semplice tecnica aggiunge delle barre ad una lista di item, dietro al testo (ecco l'esempio completo). Funziona con liste di qualunque lunghezza. Liste più lunghe traggono beneficio dall'essere ordinate in base al valore numerico perché i valori relativi delle barre sono più facili da leggere quando sono sequenziali. In questo esempio andremo a mostrare per ciascun item il valore numerico, ma si può farne a meno se i valori sono meno importanti e la cosa fondamentale è mostrare la comparazione tra i valori relativi.
Iniziamo con una lista non ordinata di link (le interruzioni di riga sono contrassegnate dal carattere »):
<ul class="chartlist"> <li> <a href="http://www.example.com/fruits/apples/">Apples</a> </li> <li> <a href="http://www.example.com/fruits/bananas/"> » Bananas</a> </li> <li> <a href="http://www.example.com/fruits/cherries/"> » Cherries</a> </li> <li> <a href="http://www.example.com/fruits/dates/">Dates</a> </li> </ul>
La prima cosa da fare è aggiungere i valori per ciascun item nella lista. Li inserirò all'interno di un elemento span
al di fuori del link in modo che possano essere trattati con gli stili separatamente:
<ul class="chartlist"> <li> <a href="http://www.example.com/fruits/apples/">Apples</a> <span class="count">420</span> </li> <li> <a href="http://www.example.com/fruits/bananas/"> » Bananas</a> <span class="count">280</span> </li> <li> <a href="http://www.example.com/fruits/cherries/"> » Cherries</a> <span class="count">200</span> </li> <li> <a href="http://www.example.com/fruits/dates/">Dates</a> <span class="count">100</span> </li> </ul>
Per creare le barre abbiamo bisogno, nel CSS, di rendere i list item come elementi block, in modo che possano assumere la larghezza piena. Imposteremo per essi il posizionamento relativo: così potremo posizionare le barre relativamente a ciascun item. Dal momento che la funzione primaria della lista è quella di essere un menu di navigazione, imposterò display:block
sui link in modo da rendere cliccabile l'intera larghezza della lista:
.chartlist li { position: relative; display: block; }
Aggiungerò anche alcuni stili per spostare i contatori sulla destra della lista. Userò il posizionamento assoluto invece del float in modo tale che i link e le barre possano sovrapporsi per tutta l'estensione del grafico:
.chartlist .count { display: block; position: absolute; top: 0; right: 0; margin: 0 0.3em; text-align: right; color: #999; font-weight: bold; font-size: 0.875em; }
Poiché abbiamo usato i posizionamenti assoluti per i contatori, aggiungerò del padding ai link per essere sicuro di avere spazio per i numeri, che andranno così a piazzarsi accanto al testo senza sovrapporsi. Si dovranno aggiungere anche un paio di regole per i link per farli sempre apparire sopra la barra che posizioneremo sotto di loro. Imposterò il loro posizionamento su relative
così che possano accettare un valore di z-index
, e imposterò lo stesso z-index
ad un numero superiore a 0 per farli stare in cima al grafico:
.chartlist li a { display: block; padding: 0.4em 4.5em 0.4em 0.5em; position: relative; z-index: 2; }
Prima di passare agli stili per le barre ho bisogno di aggiungere un elemento nel markup per ciascun item. Serve a ospitare i dati che le barre veicoleranno sotto forma di grafico. In questo caso vogliamo mostrare il valore relativo di ciascun item della lista in confronto al computo totale dell'intera lista. In questo modo l'informazione che comunicheremo con le barre sarà una percentuale calcolata in base a questi due valori. Aggiungerò un elemento al markup e gli assegnerò la classe appropriata in modo da poterlo usare nel CSS. Usare una classe con nome index
e all'interno dell'elemento (uno span
) inserirò il valore percentuale relativo:
<ul class="chartlist"> <li> <a href="http://www.example.com/fruits/apples/">Apples</a> <span class="count">420</span> <span class="index">(42%)</span> </li> <li> <a href="http://www.example.com/fruits/bananas/"> » Bananas</a> <span class="count">280</span> <span class="index">(28%)</span> </li> <li> <a href="http://www.example.com/fruits/cherries/"> » Cherries</a> <span class="count">200</span> <span class="index">(20%)</span> </li> <li> <a href="http://www.example.com/fruits/dates/">Dates</a> <span class="count">100</span> <span class="index">(10%)</span> </li> </ul>
Una nota sui dati
In questo grafico di esempio mostriamo ogni item come una percentuale dell'intero (come in un grafico a torta), ma potete usare la stessa tecnica per mostrare percentuali relative al valore più alto della lista, così ci sarà sempre almeno una barra al 100% e tutto il resto è una percentuale del valore più alto. Potete anche calcolare le percentuali relative ad un valore di base che imposterete ad un valore fisso (per esempio al 50%). In questo caso tutte le altre percentuali saranno più alte o più basse in base alla loro deviazione dal valore di base. I dati sulle performance dei nuovi chip per computer sono spesso mostrati in questo modo.
I calcoli matematici per ottenere tutto ciò sono fuori dagli scopi di questo articolo, ma il punto è che potrete usare lo stesso markup e gli stessi stili per rendere in forma di grafico tipi differenti di dati. Assicuratevi sempre di usare titoli e descrizioni chiare per i valori del grafico, comunque.
In questi esempi io uso sempre dati finti, ma ci sono molti modi per calcolare le percentuali su un sito reale. Potete calcolarle a livello di back-end e mostrarli in un template. Potete usare Javascript per estrarre la percentuale dal markup e applicarla come valore della larghezza nello stile che applicate alle barre. Nell'articolo assumeremo che i calcoli necessari siano stati già fatti, così userò sempre i valori direttamente nel markup sotto forma di stili inline:
<ul class="chartlist"> <li> <a href="http://www.example.com/fruits/apples/">Apples</a> <span class="count">420</span> <span class="index" style="width: 42%">(42%)</span> </li> <li> <a href="http://www.example.com/fruits/bananas/"> » Bananas</a> <span class="count">280</span> <span class="index" style="width: 28%">(28%)</span> </li> <li> <a href="http://www.example.com/fruits/cherries/"> » Cherries</a> <span class="count">200</span> <span class="index" style="width: 20%">(20%)</span> </li> <li> <a href="http://www.example.com/fruits/dates/">Dates</a> <span class="count">100</span> <span class="index" style="width: 10%">(10%)</span> </li> </ul>
Ultimi ritocchi al grafico a barre
Il passo finale per questo grafico consiste nell'aggiungere gli stili per le barre. Nasconderò la percentuale (usando il trucco del text-indent preso dalla tecnica di image replacement di Mike Rundle) dal momento che il valore preciso non è importante come la proporzione relativa e la barra andrà bene così com'è. Se avete bisogno di mostrare la percentuale potete farlo mostrandola all'interno della barra o su un elemento separato.
Imposterò l'altezza della barra sul 100% e, poiché imposteremo più tardi la larghezza effettiva, imposterò un valore di default di 0 così che le barre non saranno mostrate affatto senza dare ad esse un valore esplicito. Per lo sfondo ho scelto di usare un blue chiaro, il testo del link sarà così leggibile quando si sovrappone alla barra, ma le barre saranno ancora facilmente visibili:
.chartlist .index { display: block; position: absolute; top: 0; left: 0; height: 100%; background: #B8E4F5; text-indent: -9999px; overflow: hidden; }
Inserisco pure degli stili per l'hover sulle righe del grafico, dei bordi e del padding per migliorare la leggibilità: ecco l'esempio finale. Da notare (poete testarlo) come il tutto rende con gli stili disabilitati: l'informazione che veicoliamo è comunque accessibile.
Eccoci alla fine della prima parte. Nel prossimo appuntamento affronteremo la creazione di grafici per timeline.
Grafici a timeline
Una volta stabilita la ricetta di base di una classica navigazione semantica con un pizzico di dati e un po' di CSS per trasformare i dati in grafici, ci sono molte variazioni che è possibile applicare a diversi tipi di dati. Un trucchetto semplice consiste nel trasformare il grafico sul suo lato per ottenere una timeline (ecco il secondo esempio completato).
Inizierò con un markup che è molto simile a quello visto in precedenza. In questo caso è una lista di giorni, con un valore per ciascun giorno. Dal momento che ho uno spazio limitato nel formato orizzontale per mostrare le etichette per ciascuna barra, mostrerò solo il giorno del mese nell'etichetta e userò un'intestazione sopra per specificare il mese. Poiché il tutto è da intendere e realizzare come una navigazione e poiché il grafico veicolerà i valori relativi, va bene non mostrare tutta l'informazione che potremmo mostrare. Come utile aggiunta, inserirò un titolo ai link con la data completa e il contatore per quel giorno specifico, in modo che i dettagli appaiano in un tooltip per ciascuna barra. Ecco il codice HTML:
<ul class="timeline"> <li> <a href="http://www.example.com/2007/dec/1/" » title="December 1, 2007: 40"> <span class="label">1</span> <span class="count">(40)</span> </a> </li> <li> <a href="http://www.example.com/2007/dec/2/" » title="December 2, 2007: 100"> <span class="label">2</span> <span class="count">(100)</span> </a> </li> </ul>
Ripetiamo. In questo esempio ho creato un grafico con 30 giorni con una barra per ciascun giorno, ma potete dare al grafico qualunque lunghezza. Se state creando un grafico con meno barre, potete renderle più larghe e potrete anche ottenere spazio per etichette più lunghe.
Per essere sicuri che le etichette entrino nello spazio sotto le barre, andrò a dimensionare l'intero grafico usando gli em
: così le sue dimensioni si adatteranno all'aumentare o al diminurie delle dimensioni del testo. Per rendere le cose più semplici, imposterò le dimensioni del testo che voglio usare per le etichette sull'elemento principale con classe .timeline
, in modo da poter poi dimensionare tutto relativamente a quel valore. Imposterò la proprietà height
dell'intero grafico a 10 em
, cosa che lascia 8 em
per la barra e 2 em
per le etichette, usando anche un po' di padding:
.timeline { font-size: 0.75em; height: 10em; } .timeline li { height: 8em; }
Come prima, imposterò i list item perché abbiano il posizionamento relativo, perché userò il posizionamento assoluto per fissare ciascuna barra al fondo di ognuna. Floatterò i list item sulla sinistra in modo tale che le barre siano allineate una accanto all'altra in senso orizzontale. Imposterò la larghezza (width
) di ciascuna barra su 1.5 em
e l'altezza (height
) su 8 em
per avere spazio sufficiente per le etichette con due cifre che stanno sotto. Metterò un po' di padding su entrambi i lati per separare le barre. Userò gli em
per tutte le dimensioni:
.timeline li { height: 8em; position: relative; float: left; width: 1.5em; margin: 0 0.1em; }
Poiché voglio che tutta l'area della barra e l'etichetta siano cliccabili, imposterò i link su display:block
e height:100%
, così riempiranno tutto lo spazio disponibile che ho creato per i list item:
.timeline li a { display: block; height: 100%; }
Voglio che le etichette appaiano sotto le barre, ma, poiché voglio che siano cliccabili come le barre, le ho piazzate entrambe all'interno di un tag a
. Per spostare le etichette, userò il posizionamento assoluto con un valore negativo sul bottom
. Dato che le barre hanno un'altezza di 8 em
e il grafico di 10 em
, sposterò le etichette in basso di -2 em
. Imposterò un line-height
di 2 em
, così, a prescindere dalla dimensione del testo, avremo spazio sufficiente per avere le etichette al centro dello spazio verticale. Inoltre impostiamo l'allineamento del testo al centro e le fissiamo sulla sinistra:
.timeline li .label { display: block; position: absolute; bottom: -2em; line-height: 2em; left: 0; width: 100%; text-align: center; }
Poiché non mostreremo i valori numerici assoluti in questo grafico, userò l'elemento con classe count
per visualizzare la barra, usando la stessa combinazione di text-indent
e overflow
per nascondere il testo. Darò alle barre un colore di sfondo pieno e le posizionerò dalla parte bassa a sinistra dei list item. Imposto pure la larghezza al 100% e l'altezza a 0:
.timeline li a .count { display: block; position: absolute; bottom: 0; left: 0; text-indent: -9999px; overflow: hidden; width: 100%; height: 0; background: #AAA; }
Per questo grafico non voglio che ogni barra rappresenti una percentuale del totale, poiché ci sono molti item e le barre sarebbero tutte piccole. Invece, voglio che il giorno con il valore più alto rappresenti la barra più alta, così imposterò l'altezza di quell'elelento al 100% e calcolerò le altezze di tutte le percentuali rispetto a quella del giorno che ha il valore più alto. Potete vedere i risultati nell'esempio completato. Ho anche aggiunto uno stile per l'hover per evidenziare la barra, l'etichetta e l'area dello sfondo così che sia chiaro su quale item si clicca.
Grafici a sparkline
Ora che abbiamo realizzato una timeline, possiamo restringerla per creare un grafico tipo sparkline. Si tratta di un metodo comodo per mostrare un insieme di dati inline con del testo (ecco l'esempio). Dall'esempio potete vedere che di fatto abbiamo semplicemente ristretto il grafico a timeline. Con barre al posto di linee non sarà un vero grafico a sparkline, ma serve comunque a impacchettare molte informazioni in un piccolo grafico.
Il markup di partenza è un po' diverso questa volta. Poiché stiamo creando molteplici grafici, inizieremo comunque con una lista non ordinata, ma ogni list item conterrà un grafico completo. Poiché le sparklines sono intese come un modo non intrusivo per visualizzare informazioni da affiancare a del testo, possiamo provare a riflettere ciò anche nel markup usando elementi inline per ciascun punto del grafico. Ciò che cerchiamo di ottenere è qualcosa che sia facile da leggere anche senza l'applicazione di CSS. date un'occhiata all'esempio senza CSS per farvi un'idea.
Inizierò con uno span
come contenitore per il grafico, userò poi un altro span
con classe index
come contenitore per ciascuna barra. Ogni numero della serie è contenuto nel suo span
con una classe count
. Questo è quello che useremo per applicare gli stili alla barra. Poiché nasconderò il testo all'interno di ogni span.count
, ho aggiunto delle virgole tra ognuno e delle parentesi intorno all'intero set per rendere più chiaro da consultare il contenuto senza stili:
<span class="sparkline"> <span class="index"><span class="count">(60, </span></span> <span class="index"><span class="count">220, </span></span> <span class="index"><span class="count">140, </span></span> <span class="index"><span class="count">80, </span></span> <span class="index"><span class="count">110, </span></span> <span class="index"><span class="count">90, </span></span> <span class="index"><span class="count">180, </span></span> <span class="index"><span class="count">140, </span></span> <span class="index"><span class="count">120, </span></span> <span class="index"><span class="count">160, </span></span> <span class="index"><span class="count">175, </span></span> <span class="index"><span class="count">225, </span></span> <span class="index"><span class="count">175, </span></span> <span class="index"><span class="count">125)</span></span> </span>
Floatterò l'intero grafico sulla sinistra per piazzarlo vicino al testo. Usare un float qui è un po' strano, ma fino a quando non avremo un supporto migliore per la proprietà display:inline-block
, dobbiamo rivolgerci necessariamente al float. Poiché vogliamo che il grafico abbia la stessa dimensione del testo, assegnerò ad esso un height
pari a 1 em
e un po' di margine su entrambi i lati per dare respiro:
.sparkline { float: left; height: 1em; margin: 0 0.5em; }
Dal momento che gli elementi con classe .index
sono i contenitori della barra, imposteremo per essi position:relative
e li floatteremo sulla sinistra. La barra avrà una larghezza di 2px, poiché 1px è un po' troppo piccolo. L'altezza sarà uguale a quella del grafico, come nella timeline, così impostremo height
al 100%:
.sparkline .index { position: relative; float: left; width: 2px; height: 1em; }
Per le barre seguiremo lo stesso schema della timeline, applicando anche il trucchetto per nascondere il testo:
.sparkline .index .count { display: block; position: absolute; bottom: 0; left: 0; width: 100%; height: 0; background: #AAA; overflow: hidden; text-indent: -9999px; }
Aggiungerò anche un po' di stili di base e del padding alla lista non ordinata che contiene la sparkline. Ecco l'esempio finale.
Non sovrastimate la forza
Potete vedere in azione tutti i grafici in questo esempio riassuntivo. Provate ad aggiustare la dimensione del testo e osservate come come i grafici si adattino al resto della pagina. Controllate anche l'esempio senza stili per vedere come il markup degradi senza il supporto dei CSS.
Ovviamente, questi sono grafici semplici e queste tecniche non sono la migliore opzione in tutte le situazioni. Quando avete bisogno di markup semanticamente ricco, quando avete un set di dati molto ampio o molte categorie da confrontare, nulla batte le tabelle. Per visualizzazioni particolari come i grafici a torta 3D, potete scegliere di affidarvi a tecnologie server-side in grado di generare immagini. Per interazioni extra e animazioni Flash è forse la scelta da fare.
Tutto quanto abbiamo detto può comunque essere la prova che se avete bisogno di costruire ambienti visuali integrati nella struttura di siti basati su dati potete contare anche su markup semantico, accessibile e un po' di CSS.