In molti articoli della sezione CSS abbiamo fatto uso del
fast CSS rollover
per ottenere effetti rollover senza la necessità di preload, con poche e semplici
regole CSS e una singola immagine.
Abbiamo usato il rollover grafico con i CSS ad esempio nei
menu,
nei bottoni
e negli spotlight,
ma è possibile applicarlo anche ad altri elementi grafici.
È proprio quello che vedremo in questo appuntamento, in cui realizzaremo
un widget di selezione di località con grafica e CSS, cioè una mappa con
rollover.
Ecco l'esempio che accompagna l'articolo e il suo screenshot:
Vediamo innanzitutto il markup: si tratta di un titolo e di una lista non ordinata inseriti
in un div. Da notare che ogni list-item ha un id univoco, così da consentirne
l'individuazione e la personalizzazione con i CSS.
<div id="map">
<h4>Please select your location:</h4>
<ul>
<li id="europe"><a href="#">Europe</a></li>
<li id="asia"><a href="#" >Asia</a></li>
<li id="n-america"><a href="#">North America</a></li>
<li id="s-america"><a href="#">South America</a></li>
<li id="africa"><a href="#">Africa</a></li>
<li id="oceania"><a href="#">Oceania</a></li>
</ul>
</div>
Il markup è semantico e minimale, e consente di ottenere un contenuto accessibile anche a CSS disabilitati.
Ecco come rende l'esempio in assenza di CSS:
Prima di addentrarci nel CSS dell'esempio, vediamo l'immagine di sfondo che utilizza.
Si tratta di una PNG larga 250px e alta 532px, suddivisa in 5 sezioni verticali alte 133px.
Ciascuna porzione dell'immagine riproduce l'intera mappa: la prima mostra tutti i continenti in grigio, mentre nelle altre
questi sono colorati e vengono usati per il rollover. Un accorgimento indispensabile è assicurarsi che nelle varie
riproduzioni della mappa non ci siano due aree evidenziate in blu confinanti, così da ottenere un rollover perfetto su ciascuna area
geografica e solo su quella.
Siamo pronti quindi a procedere con il CSS dell'esempio, che è piuttosto corposo ma tutto sommato semplice.
Si tratta infatti di nascondere il testo della nostra mappa, dimensionare e posizionare assolutamente i link
e gestire i rollover. Cominciamo dalle regole per il div contenitore (in cui ho usato il workaround sul box
model illustrato qui sul blog)
e il titolo:
div#map{width:250px !important;width /**/:258px;
border:4px solid #999;margin:100px auto}
#map h4{margin:0;padding:5px 0;text-align:center;
background:#DADADA;color:#444;
font: bold 12px Arial,sans-serif}
Ora le regole generiche per lista, list-item e link. La lista avrà dimensioni pari a quelle della mappa
e sarà posizionata relativamente in modo da consentire il posizionamento assoluto al suo interno. Si annulleranno
margini e padding da lista e list-item, per poi nascondere il testo attraverso il text-indent
negativo e azzerare le dimensioni dei list-item. I link infine verranno posizionati assolutamente, e verrà
loro attribuita l'immagine di sfondo della mappa. Vediamo il CSS:
#map ul,#map li{margin:0;padding:0;list-style:none}
#map ul{position:relative;width:250px;height:133px;
overflow:hidden;background-image: url(map.png)}
#map li{text-indent: -9999em;width:0;height:0}
#map a{position:absolute;background-image: url(map.png)}
Non ci resta che l'ultima sezione del CSS dell'esempio, ovvero quella relativa ai singoli
link: per ciascuno di essi bisognerà specificare le coordinate left
e top
,
le dimensioni e il background-position
. Per la fase :hover basterà poi intervenire
su background-position
così da mostrare la porzione di immagine corrispondente.
Per questa fase è consigliabile, se non necessario, riaprire il programma di grafica
con cui è stata realizzata l'immagine e ottenere le informazioni necessarie attraverso
semplici selezioni. Quello che ci serve sono appunto le coordinate dell'angolo
in alto a sinistra della selezione e le sue dimesioni, che si possono ricavare
facilmente. Ecco la selezione sull'Europa e il codice per il link corrispondente nel
suo stato normale:
Da notare come, una volta determinate le coordinate left
e top
del link, quelle per background-position
si otterranno semplicemente aggiungendo
un segno meno davanti. Per la fase :hover basterà quindi ridefinire le coordinate dello sfondo,
e in particolare la seconda, ovvero quella relativa all'asse verticale. Vediamo a questo
punto le regole CSS necessarie per il link dell'Europa:
#map #europe a{left: 109px;top: 16px;
height: 41px;width: 45px;
background-position:-109px -16px}
#map #europe a:hover{background-position: -109px -149px}
È facile accorgersi che per ciò che riguarda la fase :hover la posizione verticale
dello sfondo si è ottenuta sottraendo 133px, ovvero l'altezza di una riproduzione della
mappa, dalla coordinata verticale del link in stato normale (infatti -16-133 = -149)
dato che l'immagine che contiene la fase :hover dell'Europa è la seconda. Analogamente si è proceduto per gli altri link:
si tratta di un compito un po' laborioso, ma tutto sommato semplice e meccanico.
La nostra mappa è quasi completa, manca però un piccolo accorgimento. Certe aree geografiche
si sovrappongono, e in fase :hover si otterrebbero effetti indesiderati come nello screenshot
di seguito:
Come si può notare una zona dell'Asia risulta tagliata dal link che interessa l'Africa, mostrando quindi
un rollover parziale che non corrisponde a ciò che vorremmo ottenere. Come risolvere?
Ci viene in soccorso la proprietà z-index, che regolamenta il modo in cui vengono
disposti elementi posizionati lungo l'asse perpendicolare allo schermo.
Rimando all'articolo sui posizionamenti assoluti
per una trattazione approfondita dei posizionamenti e dello z-index, basti sapere in
questo contesto che elementi con z-index
maggiore vengono disposti sopra.
Ecco quindi le regole dell'esempio in cui viene specificato lo
z-index per sistemare le cose:
map #europe a{z-index: 2}
#map #africa a:hover{z-index: 3}
#map #asia a:hover{z-index: 3}
Con le dichiarazioni aggiuntive relative allo z-index viste sopra, il nostro esempio è
praticamente ultimato. Il codice del CSS per intero è incorporato nella sezione head
di pagina per
facilità di consultazione, ma come sempre in casi reali andrebbe spostato in un CSS esterno.
Conclusioni e download
Abbiamo visto in questo articolo come sia possibile ottenere una mappa grafica con rollover
partendo da un markup semplice e usando una sola immagine. L'esempio qui visto ha una buona
compatibilità: è stato testato con successo su Internet Explorer dalla versione 5.5 alla 7,
oltre che sulle ultime versioni di Opera, Firefox e Safari.
La tecnica qui vista è applicabile anche ai menu e in particolare a tutti quegli elementi
che richiedano forme irregolari e/o strutture complesse. La tecnica è accessibile agli screen
reader e con i CSS abilitati, non lo è purtroppo in uno scenario raro ma possibile: CSS abilitati
e immagini disabilitati. È possibile risolvere utilizzando una tecnica di image replacement
alternativa, magari una tra quelle riportate nell'articolo
Image Replacement: le 3 tecniche migliori.
Codice, immagini ed esempio sono disponibili per il download. Alla prossima.