In questo articolo, suddiviso in tre parti, vedremo diversi modi per creare menu con rollover e preload solo tramite i fogli di stile. Iniziamo con il definire questi due termini inglesi ormai d'uso comune nel webdesign.
Il rollover è una tecnica che si utilizza quando si vuole cambiare la presentazione di uno o più elementi di una pagina web al passaggio del mouse da parte dell'utente. Si tratta generalmente (e aggiungo: si dovrebbe trattare esclusivamente) di elementi ipertestuali, cioè link. Infatti, è buona normale far capire all'utente, attraverso una transizione di stato, che ha appena messo il mouse sopra un link. Il rollover può essere realizzato attraverso i css e la modifica di proprietà quali bordi, colore, peso del font, sottolineatura o altro. Può anche essere realizzato modificando lo sfondo o l'elemento grafico stesso. È di questi due ultimi casi che ci occuperemo in questo articolo.
Il preload è una tecnica che consente di precaricare un'immagine di modo che, ultimato il caricamento totale della pagina, al momento del rollover l'immagine di cambio sia già disponibile sulla macchina dell'utente e non si debba aspettare il caricamento della stessa. In questo modo la transizione sarà immediata anche al primo passaggio mouse.
Come è facile immaginare, rollover e preload coinvolgono principalmente menu di navigazione, ed è di questo che ci occuperemo in questi due articoli. Si tratta di meccanismi che nel web design "vecchia maniera" venivano svolti esclusivamente con Javascript.
Orientare l'utente nella navigazione
Prima di addentrarci nella realizzazione pratica dei menu, una piccola introduzione sull'usabilità di un menu di navigazione. Ci sono alcuni principi di cui si dovrebbe tenere sempre conto:
- l'utente dovrebbe poter capire facilmente dove può andare: è quindi indispensabile avere una navigazione chiara e ben distinta dal resto della pagina, sia a livello spaziale che di colore;
- è importante distinguere i link al passaggio del mouse: questo per far capire all'utente che il cambiamento di stato del link, grazie al rollover, indica un possibile cambiamento di pagina;
- l'utente dovrebbe poter capire immediatamente dove si trova: è quindi importante distinguere la pagina/sezione corrente tramite il menu.
Vedremo nel corso dell'articolo come sia possibile tener conto facilmente delle tre regolette viste sopra e realizzarle praticamente grazie ad HTML e CSS.
Menu a due stati
Questa tecnica è ispirata all'ottimo tutorial CSS Uberlink menu di projectseven.com, apparso a metà giugno del 2003. Vedremo brevemente come realizzare un menu molto simile, con alcune piccole modifiche rispetto alla versione originale volte all'accessibilità e la compatibilità cross-browser.
Il menu presentato su Projectseven ha infatti due piccoli difetti: usa un font dimensionato in pixel e dichiara nei link dimensioni e padding, così da avere sostanziali differenze di visualizzazione tra Internet Explorer 5.x e gli altri browsers, come spiegato nel mio articolo Capire il box model. Vedremo come sia possibile evitare del tutto l'uso del padding (e di conseguenza del box model hack) ed avere un menu con testo ridimensionabile che rende in maniera omogenea su tutti i browsers.
Un menu di questo tipo usa due immagini di sfondo per i due stati dei link:
- stato normale o di riposo:
- stato attivo/hover insieme:
Lo stato attivo e lo stato hover dei link coincidono visivamente. Questa tecnica
ha due vantaggi: la pagina corrente viene evidenziata e l'immagine di sfondo per
lo stato hover è così già precaricata per il rollover.
Iniziamo a vedere il codice HTML per il nostro menu. Si tratta di una lista.
Racchiudere una serie di link per la navigazione in una lista è la scelta più
'semantica' e logica:
<div id="navigation">
<ul>
<li id="activelink"><a href="#">Home</a></li>
<li><a href="#">Grafica</a></li>
<li><a href="#">Webdesign</a></li>
<li><a href="#">Php</a></li>
<li><a href="#">Css</a></li>
</ul>
</div>
Credo che tutti sappiate come rende una lista senza stile. Vediamo subito come la trasformeremo.
Evidenziare la pagina corrente
Prima ho parlato di stato attivo di un link, vediamo di cosa si tratta
e come sia possibile realizzarlo tramite HTML e fogli di stile. Un link in stato
attivo serve ad evidenziare la pagina corrente. Torniamo all'esempio. Quando mi
sposto da una sezione all'altra la voce del menu corrispondente assumerà
un aspetto diverso dagli altri. Come dicevamo è un modo semplice per 'ricordare'
all'utente dove si trova.
Cosa devo fare per ottenere l'effetto? Nelle pagine di ciascuna sezione dovrò
assegnare all'elemento della lista contenente il link corrispondente un selettore
di id, unico in tutta la pagina. Nelle pagine (in tutte le pagine!) della
sezione "CSS", per esempio, mi basterà fare così:
<li><a href="index.html">Home</a></li>
<li><a href="php.html">Php</a></li>
<li id="activelink"><a href="css.html">Css</a></li>
Si noti come l'id activelink viene assegnato al list-item
contenente il link che punta alla pagina corrente. Il css attraverso una regola
specifica si occuperà di evidenziarlo.
Nota: lo stato attivo di cui si parla in questo articolo
non ha niente a che fare con la pseudoclasse :active. Infatti,
questa pseudoclasse non garantisce uno stato persistente e impostabile via codice
html: è per questo che si farà uso di un id.
Preparare il foglio di stile
Una volta preparate le due immagini di sfondo, si può procedere ad elaborare il foglio di stile. Definiamo la regola per l'ul, eliminando margini, padding e disco:
div#navigation ul{list-style-type: none;margin: 0;padding: 0}
Ora il list item li. Eliminiamo il padding e lasciamo solo un
leggero margin (3 pixel) per separare verticalmente gli elementi della navigazione:
div#navigation li{margin: 0 0 3px;padding: 0}
E veniamo agli stili sui link, la parte centrale del menu. Diamo al link un
display: block per poter attribuire loro delle dimensioni e far si
che si dispongano verticalmente uno sull'altro. In realtà assegnamo ai link solo
la larghezza; per l'altezza infatti useremo il line-height che serve
a due scopi: dare un' altezza ai link e centrare verticalmente il testo all'interno,
indipendentemente dalla dimensione del font. Inoltre ci consente di evitare l'uso
del padding verticale. Ora per spostare il testo dal bordo sinistro del link useremo
la proprietà text-indent che dà in questo caso un effetto identico
a quello che si avrebbe usando invece il padding-left.
Aggiungiamo bordi, background e proprietà sul font e la nostra regola è pronta:
div#navigation a{display: block;width: 150px;line-height: 30px;
text-decoration: none; border: 1px solid #666;text-indent: 30px;
background: url("bknormal.jpg") no-repeat top left;
color: #333;font-variant: small-caps}
Per lo stato attivo (che verrà specificato attraverso un selettore di id) e lo stato :hover
le regole da modificare sono solo quelle sullo sfondo e sul colore del testo che differiscono
dalla regola precedente. Infine giochiamo sul colore del testo dei due elementi, dato che hanno
in comune il background:
div#navigation a:hover{
background: url("bkactive.jpg") no-repeat top left;color: #1F2A3E}
div#navigation li#activelink a,div#navigation li#activelink a:hover{
background: url("bkactive.jpg") no-repeat top left;color: #fff}
Arrivati a questo punto il nostro menu è completo. Rivediamo l'esempio
finito, composto da cinque pagine HTML praticamente uguali: l'unica differenza
è l'id "activelink" assegnato al list-item per evidenziare la pagina corrente.
Menu a tre stati
L'idea del fast
css rollover presentata da Petr Stanicek è molto semplice e allo stesso tempo
geniale. Una proprietà ben supportata dai browser e poco conosciuta è background-position.
Questa proprietà supporta valori in pixel e ammette anche valori negativi. Così
la tecnica è questa: preparare una sola immagine di sfondo che racchiude
i tre stati dei link, e agire sul background-position per avere le transizioni.
Ecco l'immagine che ho preparato per questo menu:
Da sinistra verso destra, abbiamo lo stato di riposo, lo stato hover e lo stato
attivo. I tre sfondi sono larghi ciascuno 120pixel e alti 30, e sono separati
da uno spazio bianco di dieci pixel. Notare che i tre sfondi combinati nell'unica
immagine dovranno essere precisi al pixel, e si potranno disporre in
orizzontale o verticale: l'importante è conoscere le coordinate d' inizio di ciascuno.
Per questo esempio vedremo un menu
orizzontale a tre stati. Il codice HTMLè uguale all'esempio precedente.
<div id="navigation">
<ul>
<li id="activelink"><a href="#">Home</a></li>
<li><a href="#">Grafica</a></li>
<li><a href="#">Webdesign</a></li>
<li><a href="#">Php</a></li>
<li><a href="#">Css</a></li>
</ul>
</div>
Ora procediamo con i CSS. Per prima cosa operiamo sull'ul, eliminando
margini, padding e disco:
div#navigation ul{list-style-type: none;margin: 0;padding: 0}
Ora i list-item: eliminiamo il padding, rendiamoli float così da poterli affiancare,
e lasciamo solo un margine sul lato destro così da poterli distanziare. Ecco la regola:
div#navigation li{float: left;margin: 0 3px 0 0;padding:0}
A questo punto i link: allo stesso modo dell'esempio precedente rendiamoli block-level, assegnamo le dimensioni,
il background, font, line-height e text-indent per sistemare il testo:
div#navigation a{display: block;width: 120px;line-height: 30px;
text-decoration: none; border: 1px solid #666;
background: url("sfondocombinato.jpg") no-repeat top left;color: #333;
font-variant: small-caps;text-indent: 27px}
L'immagine di sfondo è composita, e per avere l'effetto rollover sui link ci
basterà giocare sulla posizione del background. Per la proprietà background-position
vanno specificate nell'ordine la coordinata orizzontale (asse x) e la coordinata
verticale (asse y) dello sfondo. Dando un valore negativo alla coordinata x, trasliamo
lo sfondo verso sinistra, mostrando quindi lo sfondo dello stato hover:
div#navigation a:hover{background-position: -130px 0;color: #336}
Ora lo stato attivo: anche in questo caso interveniamo solo sulla posizione di background e il colore. Se vogliamo
però che il link attivo (contenuto nel listitem con id="activelink") non risenta della regola definita sopra, dovremo dichiararne
una più specifica per il suo stato hover, che raggrupperemo con lo stato di riposo. Non ha senso infatti avere un effetto
rollover su un link che è già attivo. Vediamo il codice:
div#navigation li#activelink a,div#navigation li#activelink a:hover{
background-position: -260px 0;color: #fff}
A questo punto il nostro menu è ultimato. Nel caso dell'esempio si tratta solo
di preparare cinque pagine in cui, di volta in volta si assegna l'id activelink
alla pagina per evidenziare la sezione (o la pagina) corrente: rivediamolo
in azione.
Uno strano comportamento di Internet Explorer
Il menu che abbiamo appena visto funziona sui più diffusi browser moderni,
IE5.x, IE6, le versioni recenti di Opera e quelli gecko-based. C'è un piccolo
problema però con Internet Explorer e il CSS rollover: il fenomeno in inglese
viene chiamato flickering, che significa sfarfallìo, intermittenza.
In sostanza in Internet Explorer il rollover non è istantaneo ma c'è un po' di
tempo di attesa, in cui sembra che l'immagine di sfondo venga ricaricata ogni
volta. Questo strano fenomeno sparisce modificando le impostazioni dei file temporanei
in questo modo:
Strumenti > Opzioni > Impostazioni dei file temporanei internet > proprietà:
a questo punto selezionare "automaticamente". Certo non possiamo dire ai nostri
utenti di modificare le opzioni del browser: se è accettabile il piccolo difetto
di questa tecnica, la possiamo usare tranquillamente. Altrimenti possiamo pensare
ad un'alternativa. Vediamola.
Menu a tre stati con immagini separate
Un modo per avere un menu rollover a tre stati evitando l'uso del background-position
c'è. L'idea è semplice.. ecco le tre immagini di sfondo separate che useremo per
il prossimo menu:
- stato normale:
- stato hover:
- stato attivo:
Lo stato normale viene dato come sfondo al link, mentre lo stato hover viene
dato come sfondo al list-item. Al passaggio del mouse sul link, la sua immagine
di sfondo viene tolta così da mostrare quella del li, quindi dello
stato hover.
L'immagine dello stato hover risulta così già caricata, e viene resa disponibile
subito. Vediamo il
risultato. Il codice HTML è identico ai due esempi precedenti. Ecco il CSS
completo di questa tecnica:
div#navigation{width: 600px;border-bottom: 2px solid #B9998C;
padding-top: 20px;background-color: #fff}
div#navigation ul{list-style-type: none;margin: 0;padding: 0}
div#navigation li{float: left;margin: 0;padding:0;
background: url("sfondohover.jpg") no-repeat top left}
div#navigation a{display: block;width: 120px;
line-height: 30px;text-decoration: none;
background: url("sfondonormale.jpg") no-repeat top left;
color: #666;text-align: center}
div#navigation a:hover{background-image: none;color: #503325}
div#navigation li#activelink a,div#navigation li#activelink a:hover{
background: url("sfondoattivo.jpg") no-repeat top left;color: #6B4131}
Anche in questo caso l'esempio è costituito di cinque pagine in cui si è evidenziata
la voce del menu corrispondente.
Abbiamo visto brevemente tre modi di avere rollover e preload in menu semigrafici, cioè menu costituiti da immagini di sfondo e testo normale che si sovrappone. In tutti e tre gli esempi visti il font usa una misura relativa, quindi è ridimensionabile. A questo proposito, un piccolo suggerimento: nel preparare menu simili è necessario assicurarsi che il testo sia totalmente contenuto nel link (e quindi non oltrepassi lo sfondo) anche con la dimensione del carattere del browser più grande. Basta poi divertirsi dieci minuti con un qualsiasi programma di grafica (io ho usato Pixia, un freeware leggero e versatile) per avere un menu decisamente accattivante, con codice semantico e leggero, senza l'uso di preload mediante Javascript e attenente agli ultimi standard del webdesign.
Vedremo due tipologie di menu totalmente grafici: quei menu cioè in cui l'informazione testuale è contenuta nell'immagine stessa. Anche in questo caso, saranno con rollover e preload tramite i fogli di stile.
Ecco uno zip con tutti gli esempi fin qui visti..
Occupiamoci di menu totalmente grafici in cui l'informazione testuale è parte dell'immagine. Prima di entrare nel vivo dell'articolo, ci sono alcune questioni preliminari da considerare.
Leggibilità nella grafica
Abbiamo carta bianca: potremmo usare i colori, le immagini e i font che più ci piacciono. Ma dobbiamo sempre tenere in considerazione tutte le possibili fasce di utenza del sito: è importante, per esempio, che il testo all'interno della grafica possa garantire la leggibilità anche a persone con problemi di vista, e non solo.
Orientare l'utente attraverso la grafica
Nella prima parte dell'articolo abbiamo parlato a fondo dei tre stati dei link: normale, hover e attivo e di come sia importante differenziarli. L'uso di immagini ci consente molta libertà in questa differenziazione. Eccone alcune idee:
- giocare sul colore del testo, di sfondo o sul contrasto;
- aggiungere elementi grafici oltre il testo e giocare su forma e colore di questi ultimi;
- agire sul font, cambiarne il peso o lo stile;
- usare effetti grafici:dissolvenza, sfumature, ombre ecc..
Quale che sia la tecnica usata, basterà divertirsi con un programma di grafica e preparare le immagini, tenendo sempre presente che non sono solo gli "effetti speciali" a fare un buon sito.
Tornando ai nostri tre stati, quello attivo dovrà risultare facilmente distinguibile e di spicco, mentre lo stato hover dovrà essere più nitido, denso o comunque "acceso" rispetto allo stato normale. Il principio fondamentale è che i tre stati nell'ordine normale, hover e attivo dovrebbero avere una sorta di "progressione grafica".
Peso di una pagina web
I menu totalmente grafici comportano un uso massiccio di immagini: uno degli elementi che più contribuisce a far aumentare il peso di una pagina web. Per calcolare il peso totale di una pagina web basterà sommare il peso del codice (HTML, CSS e Javascript) con quello di immagini e background. A questo punto possiamo stimare il tempo di caricamento della pagina nel caso peggiore. Se è vero che molti utenti dispongono di una connessione ADSL, ce ne sono ancora parecchi con modem a 56k. Una connessione 56k consente una velcità di download che oscilla tra 3,5 Kbyte al secondo e 5 Kbyte al secondo. Considerando la velocità di connessione minima, il peso massimo di una pagina web per un tempo di attesa di 10 secondi varia tra i 35 e 50 Kilobyte. Attenzione ed equilibrio, dunque.
Menu grafico a tre stati con image replacement
Una possibile soluzione per realizzare un menu totalmente grafico è usare una tecnica di image replacement combinandola con il fast css rollover. Una soluzione a cui ha già pensato Dan Cederholm presentandola in questa pagina. L'autore usa la LIR come tecnica di image replacement e il fast css rollover per gestire il rollover tra le immagini. La tecnica è stata però criticata in quanto a immagini disabilitate non consente di usare il menu: infatti, il testo sotto l'immagine non è visibile.
Anche Dave Shea, in un articolo uscito di recente su Alistapart, propone una soluzione che combina il fast rollover e una tecnica di image replacement, lasciando però al lettore la scelta su quale adottare. Nel momento in cui preparavo questo articolo, avevo già pronto l'esempio che vado a presentarvi. Non ho avuto dubbi sulla scelta della tecnica di image replacement da utilizzare: la cover-up. Questa tecnica infatti presenta un piccolo svantaggio a livello di markup, richiedendo uno span aggiuntivo (peraltro senza contenuto testuale, quindi vuoto e totalmente ininfluente sulla pagina senza stile), ma non necessita di hack e sopratutto non nasconde nè sposta il testo: lo copre solamente grazie ad un' immagine di sfondo. Così, a immagini disabilitate il testo dei link sarà comunque visibile.
Vediamo il codice HTML del menu totalmente grafico che andremo a creare. Anche in questo caso si tratta di una lista:
<div id="navigation">
<ul>
<li id="one"><a id="current" href="#"><span></span>Home</a></li>
<li id="two"><a href="#"><span></span>Grafica</a></li>
<li id="three"><a href="#"><span></span>Webdesign</a></li>
<li id="four"><a href="#"><span></span>Php</a></li>
<li id="five"><a href="#"><span></span>Css</a></li>
</ul>
</div>
Come si può notare si è assegnato un id unico ad ogni elemento della lista di navigazione, così da poter identificare univocamente ogni singola voce del nostro menu. Inoltre è stato aggiunto un id "current" al link che punta alla pagina corrente e che serve ad evidenziarlo via CSS.
Ora, prima di occuparci del foglio di stile, diamo uno sguardo ad una delle immagini che useremo per il menu. Per evidenziare il fatto che si tratta di un'immagine sola, e per far si che si distingua dallo sfondo di questa pagina, ho aggiunto un bordino rosso via CSS:
È un immagine di 470x40 pixels, composta da tre sezioni larghe 150 pixels e separate da uno spazio bianco di 10 pixels. Come per l'esempio con background e fast rollover della prima parte dell'articolo, le immagini dovranno essere perfette al pixel. Per questo tipo di menu con image replacement, il fast rollover è praticamente necessario: come nel caso dell'esempio della prima parte dell'articolo, giocheremo sul background-position.
Da sinistra verso destra abbiamo nell'immagine lo stato normale, lo stato hover e lo stato attivo. Allo stesso modo e con le stesse dimensioni ho preparato altre quattro immagini per le altre voci del menu.
Per questo esempio ho realizzato un menu verticale totalmente grafico. Ma vediamo come si procede a realizzare un menu simile grazie ai fogli di stile. Per prima cosa occupiamoci del div contenitore per il menu, della lista e dei list-item:
div#navigation{float: left;padding-top: 20px}
div#navigation ul{list-style-type: none;margin: 0;padding: 0}
div#navigation li{margin: 0 0 3px;padding: 0;border: 1px outset #000}
A questo punto occupiamoci dei link e degli span. Attribuiamo display:block e dimensioni ai link, mentre lo span lo posizioniamo assolutamente all'interno del link che lo contiene. Per fare ciò dichiariamo il link position:relative. Lo span, essendo posizionato assolutamente, verrà reso automaticamente display:block e di default la sua posizione sarà nell'angolo in alto a sinistra del link. Assegnamogli le stesse dimensioni del link e il gioco è fatto:
div#navigation a{
position: relative;
display: block;
width: 150px;
height: 40px
}
div#navigation a span{
position: absolute;
width:150px;
height: 40px;
cursor: pointer; /*per IE*/
}
Per qualche strano motivo lo span così posizionato in Internet Explorer perde il cursore "a manina", basterà riassegnarlo via CSS con questa dichiarazione: cursor: pointer.
A questo punto occupiamoci della fase relativa al rollover e allo stato attivo. Come al solito è IE a darci i maggiori problemi. Sembra che non capisca una regola che usa la discendenza su a:hover se questa regola non è definita prima. Così aggiungiamo una regola totalmente inutile e ininfluente che però sistema le cose. Questa è quindi la parte contrale che usa il rollover CSS:
div#navigation a:hover{color: #369 /*per IE*/}
div#navigation a:hover span{background-position: -160px 0}
div#navigation a#current span{background-position: -320px 0}
Si noti come, avendo tutti i li un' id, l'id per il link attivo è stato assegnato al link e non al list-item che lo contiene.
A questo punto non ci resta che definire le immagini di sfondo per le varie voci del menu:
li#one span{background: url("IRhome.jpg")}
li#two span{background: url("IRgrafica.jpg")}
li#three span{background: url("IRwebdesign.jpg")}
li#four span{background: url("IRphp.jpg")}
li#five span{background: url("IRcss.jpg")}
Il nostro menu totalmente grafico è così completo. Anche in questo caso, come negli esempi della prima parte, si tratta di cinque pagine così da potervi mostrare lo stato attivo su ogni singola voce del menu.
C'è ancora una cosa di cui ci dovremmo preoccupare: la stampa. Essendo l'immagine dei link definita tramite background, difficilmente verrà stampata da un qualsiasi browser dato che le impostazioni di stampa per default non consentono la stampa delle immagini di sfondo. Allo stesso modo in cui le varie voci dei link vengono comunque visualizzate a immagini disabilitate dato che vengono solo coperte da un background, così è anche per la stampa. Per una stampa migliore comunque ci basterà attribuire un' altezza automatica e magari un font che può andare bene. Ecco quindi il CSS per la stampa del nostro menu:
<style type="text/css" media="print">
div#navigation li a{height: auto;padding: 0.2em 0;
font: bolder 1.4em "Arial Black",arial,sans-serif;
color: #000;text-decoration:none;text-align:center}
div#navigation a span{display: none}
</style>
Il CSS è incorporato negli esempi per agevolarne la consultazione, ma in casi reali bisognerà preparare due fogli di stile esterni, di cui uno per ridefinire le regole di stampa.
Trasformare il menu verticale in menu orizzontale
Già dalla prima parte dell'articolo spero sia stato chiaro al lettore che realizzare menu di navigazione grazie alle liste consente un codice HTML leggero e altamente personalizzabile via fogli di stile. Con lo stesso codice HTML dell'esempio appena visto è infatti possibile ottenere un menu orizzontale con image replacement. In sostanza si tratta di rendere float ciascun list-item, di modo che così le varie voci del menu risultino affiancate. Ho preparato velocemente delle immagini per il menu, ciascuna di dimensioni 410x40pixels. Vediamone un paio, anche in questo caso con un bordino rosso attorno:
Anche in questo caso le tre posizioni orizzontali dei tre stati coincidono per tutte le immagini, così da poter gestire facilmente in modo comune il rollover attraverso il background-position. Ma ho voluto assegnare attraverso i fogli di stile diverse larghezze alle varie voci del menu. Essendo ciascuna voce del menu determinabile attraverso l'id unico assegnato ad ogni list-item, è infatti possibile attribuire diverse larghezze ai link, mentre l'altezza è ovviamente comune.
Infatti in un menu orizzontale, soprattutto grafico, è opportuno minimizzare la larghezza delle singole voci, così che le nostre pagine siano adatte a tutte le risoluzioni.
Ecco il risultato. Anche in questo caso si tratta di cinque pagine in cui il CSSè identico, mentre via HTML si è solo spostato l'id current al link per evidenziare la pagina corrente. Vediamo il css per intero:
<style type="text/css">
div#navigation ul{
list-style-type: none;
margin: 0;
padding: 0
}
div#navigation li{float:left;
margin: 0 2px 0;
padding:0;
border: 1px solid #CCC
}
div#navigation a{
position:relative;
display:block;
height: 37px
}
div#navigation a span{
position:absolute;
width:100%;
height:100%;
cursor: pointer; /*per IE*/
}
div#navigation a:hover{
color: #369; /*per IE*/
}
div#navigation a:hover span{
background-position: -140px 0;
}
div#navigation a#current span{
background-position: -280px 0;
}
/*viene attribuita la larghezza di ogni singolo link*/
li#one a{width: 65px}
li#two a{width: 90px}
li#three a{width: 120px}
li#four a{width: 45px}
li#five a{width: 45px}
/*si dichiarano le immagini*/
li#one span{background: url("HRhome.jpg") no-repeat top left}
li#two span{background: url("HRgrafica.jpg") no-repeat top left}
li#three span{background: url("HRwebdesign.jpg") no-repeat top left}
li#four span{background: url("HRphp.jpg") no-repeat top left}
li#five span{background: url("HRcss.jpg") no-repeat top left}
</style>
<style type="text/css" media="print">
div#navigation li a{display: inline;padding: 0.2em;
font: bolder 1.4em "Arial Black",arial,sans-serif;
color: #000;text-decoration:none;text-align:center}
div#navigation a span{display: none}
</style>
In questa seconda parte dell'articolo sui menu abbiamo visto menu totalmente grafici grazie ad una tecnica di image replacement. Il codice risulta semantico e "quasi" minimale, a parte lo span che abbiamo usato per l'aggiunta di immagini tramite la cover-up span. Da notare che è possibile utilizzare un'altra tecnica di image replacement, con il vantaggio di non usare markup aggiuntivo. D'altra parte, quest'ultima avrà sicuramente due svantaggi rispetto a quella usata qui: non mostrerà il testo a immagini disabilitate e richiederà hack per garantire la compatibilità multi-browser. I menu realizzati risultano accessibili con screen reader e browser testuali e sono utilizzabili a immagini disabilitate. Come al solito, ecco l'archivio zip contenente tutti i file degli esempi con il codice e le immagini.
Vedremo come sia possibile creare menu che vengono stampati fedelmente alla versione su schermo, gestendo il rollover anche sulle immagini oltre che sugli sfondi. Tutto senza una riga di Javascript, e con HTML e CSS attenenti agli standard.
Abbiamo visto come ottenere un menu grafico attraverso l'image replacement: il pregio è la possibilità di definire il nostro menu totalmente tramite i fogli di stile. Il "diffetto" più grande, come abbiamo visto, è la stampa.
Per risolvere il problema della stampa, come anticipato in chiusura della seconda parte, l'unica soluzione è usare il tag img per includere le immagini. Questo rappresenta, a parer mio, un singificativo svantaggio: un forte legame con l'HTML e la scarsa personalizzazione delle pagine tramite i fogli di stile. Nel momento in cui dovessimo procedere ad un restyling del sito e cambiare l'aspetto del menu, ci troveremmo a dover metter mano per prima cosa al codice HTML, cosa che invece non succede con un menu semigrafico o che usa una tecnica di image replacement (come abbiamo visto nelle prime due parti dell'articolo).
Addio tabelle e Javascript
Basta fare un giro in rete e dare un'occhiata al codice di siti con menu grafici per rendersi conto che la maggior parte usa le tabelle per contenere i link e Javascript per gestire il rollover. Abbiamo visto come le liste per i menu di navigazione consentono, attaverso la sola modifica del foglio di stile, di avere un menu orizzontale o verticale, al contrario delle tabelle che determinano con forza la disposizione del loro contenuto. Inoltre, l'uso delle tabelle dovrebbe essere limitato a dati tabellari: per via logica, un menu non può essere altro che una lista di collegamenti ipertestuali.
Il codice risultante da menu grafici con tabelle, immagini e rollover in Javascript risulta piuttosto pesante e difficile da gestire. Questo il codice per una singola voce di menu grafico "vecchia scuola":
<table border=0>
<tr><td><a href="#" onmouseover="document.home.src='homehover.jpg'" onmouseout="document.home.src='home.jpg'"><img src="home.jpg" name="home" border=0></a></td>
<!-- eccetera... -->
</tr>
</table>
Oltre alla complessità del codice, va anche considerato il fatto che
le immagini per gli effetti rollover vanno precaricate, sempre con Javascript,
con un onload al momento di caricare
la pagina. Vedremo in questa terza e ultima parte come sia possibile avere un
codice HTML decisamente migliore, evitare Javascript e gestire rollover e preload
unicamente grazie ai fogli di stile.
Menu orizzontale con immagini nell'HTML
Anche in questo caso si tratta di una lista di navigazione. Questa volta,
però, all'interno dei singoli link ci sarà un'immagine. A questo proposito, non
dimenticate l'attributo alt:
è l'unico modo per associare un'informazione testuale ad un'immagine, questa verrà
mostrata in browsers testuali, screen reader e dispositiivi alternativi (senza
dimenticare che tale attributo è necessario per la validazione del codice HTML).
Per questo menu ho preparato tre immagini per ciascun link del menu,
che rappresentano i tre stati. Ecco quelle relative alla voce "home":
Da sinistra verso destra abbiamo lo stato normale, lo stato hover e lo stato
attivo. Anche per questo esempio è importante che le immagini siano precise al
pixel e abbiano le stesse dimensioni.
In totale sono necessarie, per l'esempio che andremo
a realizzare, quindici immagini, ovvero tre immagini per ogni link. Non verranno
mai visualizzate tutte e quindici su una singola pagina: infatti, in ogni pagina
c'è un'immagine che corrisponde al link attivo, quattro immagini per lo stato
normale degli altri link e altre quattro per il loro stato hover. In totale, quindi,
le immagini che dovranno essere caricate su ogni singola pagina sono nove. Iniziamo
subito a vedere il codice HTML:
<div id="navigation">
<ul>
<li id="one"><a id="current" href="#"><img src="homeattivo.jpg" alt="home page"></a></li>
<li id="two"><a href="#"><img src="grafica.jpg" alt="grafica"></a></li>
<li id="three"><a href="#"><img src="webdesign.jpg" alt="webdesign"></a></li>
<li id="four"><a href="#"><img src="php.jpg" alt="php"></a></li>
<li id="five"><a href="#"><img src="CSS.jpg" alt="CSS"></a></li>
</ul>
</div>
Come si può notare, viene assegnato un id
unico ad ogni list-item e un id=current
al link in stato attivo per evidenziare la pagina/sezione corrente. Quest'ultimo
link racchiude l'immagine in stato attivo. Per gli altri quattro link
invece viene indicata l'immagine in stato normale. Si noti, quindi, come per evidenziare
le pagine appartenenti alle altre quattro sezioni le modifiche da fare in questo
caso saranno due a livello di codice HTML: spostare l'id current al link e includere
l'immagine in stato attivo relativa a quella sezione.
Il foglio di stile
Il meccanismo del rollover e preload con immagini via CSS è molto simile a
quello dell'ultimo esempio della prima parte. Sotto ogni immagine del menu c'è
un'immagine di sfondo che rappresenta lo stato hover. Lo sfondo è già caricato
e quindi il preload è implicito. Al passaggio del mouse su un link, l'immagine
viene nascosta mostrando così l'immagine in stato hover.
Vediamo come procedere con il foglio di stile. La prima cosa da fare è togliere
il bordo alle immagini:
img{border-width: 0}
Poi operiamo sulla lista e i suoi elementi, come al solito. Eliminiamo margini,
padding e disco dall'ul, rendiamo float
ogni list-item togliendo anche qui margin e padding:
div#navigation ul{list-style-type: none;margin: 0;padding: 0}
div#navigation li{float: left;margin: 0;padding:0}
A questo punto operiamo sui link. Rendiamoli block-level, questa volta però
senza assegnare nessuna dimensione: ci penserà l'immagine a dargliene una, e dato
che i link sono contenuti dentro elementi float, questi avranno la larghezza giusta
al loro contenuto pur essendo dichiarati block. Non attribuire dimensioni via
CSS nè ai list-item nè ai link ha un grosso vantaggio: poter usare immagini a
larghezza diversa senza doverle specificare via CSS. Ecco la regola:
div#navigation a{display:block}
Ora occupiamoci del rollover. Come per gli esempi della seconda parte, dobbiamo
in qualche modo dichiarare una regola che serve ad Internet Explorer per poter
usare dichiarazioni che sfruttano il selettore discendente sullo stato hover dei
link. Anche in questo caso si tratta di una regola totalmente ininfluente e non
dannosa per la resa sugli altri browsers. Stranamente, in questo caso, l'unica
regola possibile sembra il line-height.
Ora, al passaggio del mouse sul link, quello che vorremo fare è nascondere l'immagine.
Dato che non abbiamo dichiarato dimensioni l'unico modo per far "sparire"
le immagini mantenendo le dimensioni del link è usare la proprietà visibility:
div#navigation a:hover{line-height: 1px; /*serve per IE*/}
div#navigation a:hover img{visibility: hidden}
Attraverso una regola più specifica, evitiamo che avvenga il rollover sul link in stato attivo che dovrebbe
essere persistente:
div#navigation a#current:hover img{visibility: visible}
Non ci resta che definire le immagini di sfondo, e il nostro CSS è ultimato:
li#one{background: url("homehover.jpg") no-repeat top left}
li#two{background: url("graficahover.jpg") no-repeat top left}
li#three{background: url("webdesignhover.jpg") no-repeat top left}
li#four{background: url("phphover.jpg") no-repeat top left}
li#five{background: url("CSShover.jpg") no-repeat top left}
Il foglio di stile risulta abbastanza leggero, e ci consente preload e rollover
senza Javascript: rivediamo l'esempio ultimato.
Rendere il menu verticale
Come abbiamo detto in apertura, dichiarare immagini nell'HTML ha un basso livello
di personalizzazione. Se volessimo cambiare la grafica al menu dovremmo cambiare
il codice HTML. O, in alternativa, sovrascrivere le immagini con le nuove, mantenendo
i nomi dei file. Questo potrebbe però dare dei problemi con le immagini in cache
sul browser dell'utente.
Senza modificare l'HTML dell'esempio appena visto si può però intervenire sul
foglio di stile rendendo il menu verticale. Le immagini
sono state inizialmente pensate per un menu orizzontale, ho pensato quindi di
"chiuderle" con un bordo inferiore, dando un "effetto cappello". Le
modifiche al foglio di stile sono veramente minime, vediamo il CSS per intero:
div#navigation{float: left;padding-top: 20px}
div#navigation ul{list-style-type: none;margin: 0;padding: 0}
div#navigation li{margin: 0;padding:0}
div#navigation a{display:block;border-bottom: 3px solid #000}
div#navigation a:hover{line-height: 1px; /*serve per IE*/}
div#navigation a:hover img{visibility: hidden}
div#navigation a#current:hover img{visibility: visible}
li#one{background: url("homehover.jpg") no-repeat top left}
li#two{background: url("graficahover.jpg") no-repeat top left}
li#three{background: url("webdesignhover.jpg") no-repeat top left}
li#four{background: url("phphover.jpg") no-repeat top left}
li#five{background: url("CSShover.jpg") no-repeat top left}
Come al solito, ecco l'archivio zip con codice completo, immagini ed esempi visti.
Spero che sia passato essenzialmnte un messaggio: che la progettazione con i fogli di stile consente un alto livello di personalizzazione, un codice leggero e attinente agli ultimi standard del webdesign. Nel decidere quale tecnica utilizzare per realizzare un menu, grafico o semigrafico, il mio consiglio è di considerare bene i pro e i contro di cui abbiamo parlato strada facendo e di preparare immagini chiare e leggere in peso.
Fissiamo un dettaglio importante riguardante i menu con immagini visti nella terza parte, e presenterò una versione leggermente differente del menu con image replacement visto in precedenza.
Prima di cominciare, ci tenevo a precisare un piccola nota sui menu con immagini come contenuto dell'HTML. Su questo tipo di menu, come ho detto, ho alcune riserve per via della loro scarsa personalizzazione (anche se li ritengo migliori dei menu con rollover in Javascript). Inoltre, per ciascuna voce del menu andranno create tre immagini (una per ogni stato): un lavoro grafico non indifferente. Quanto al CSS usato nella tecnica, per maggiore consistenza cross-browser, ho notato che è opportuno dichiarare nel CSS le dimensioni delle immagini che compongono il menu: questo è sufficiente per fissare dello spazio extra e indesiderato che si viene a creare in particolare nei menu verticali su Internet Explorer e Mozilla.
Menu con rollover e image replacement: la nuova versione
Vedremo ora una versione piuttosto differente del menu già visto. Anche in questo caso si tratta di un menu a tre stati con fast css rollover e image replacement: rispetto alla versione già vista presenta sostanziali miglioramenti. Tra questi una maggiore compatibilità cross-browser, un codice HTML più leggero, un migliore modo di evidenziare la attiva voce del menu e soprattutto evitare il flickering di Internet Explorer.
Il flickering è un fenomeno per cui un'immagine che dovrebbe essere già caricata nella cache del browser viene richiesta nuovamente. Comporta due svantaggi notevoli: il primo è che l'utente si vedrà per un attimo il tipico cursore a clessidra e passeranno alcuni millisecondi (fino ad arrivare ad uno-due secondi circa se l'utente dispone di una connessione con modem analogico) prima che l'immagine venga visualizzata. Il secondo svantaggio è il carico del server: Internet Explorer ad ogni rollover richiederà nuovamente l'immagine, generando traffico inutile sul server, e quindi spreco di banda. Il flickering su Internet Explorer avviene solo in determinati casi, e dipende dalle impostazioni del browser. Ci sono diversi modi per evitarlo, se ne parla esaustivamente in questo articolo. La versione che stiamo per vedere non presenta flickering, e ha i diversi vantaggi cui ho accennato. Vediamola.
Ecco subito l'esempio che andremo passo passo a costruire con HTML e fogli di stile. Si tratta di un menu grafico a cinque voci, ed è costituito da cinque pagine in cui viene evidenziata la relativa voce attiva del menu.
Il codice HTML
Ecco il codice HTML, anche in questo caso si tratta di una lista non ordinata:
<body id="home">
<div id="nav">
<ul>
<li id="mhome"><a href="#">Home</a></li>
<li id="mgrafica"><a href="#">Grafica</a></li>
<li id="mweb"><a href="#">Webdesign</a></li>
<li id="mcss"><a href="#">Css</a></li>
<li id="mjs"><a href="#">Javascript</a></li>
</ul>
</div>
</body>
Da notare che nel codice ho riportato l'apertura (e la chiusura) del tag body, a cui viene assegnato un id. È proprio grazie a questo id che si potrà evidenziare la voce attiva del menu. Il codice che abbiamo visto sopra si riferisce alla home page, e presenta id="home". Gli id per le altre voci sono rispettivamente: grafica, web, css e js. Ciascuna pagina del sito dovrà quindi riportare un id al body per "poter segnalare" al CSS, come vedremo in seguito, la voce del menu corrispondente alla sezione di appartenenza. Attribuire un id al body ha un indubbio vantaggio rispetto all'attribuirlo direttamente al link: è infatti possibile, oltre che evidenziare la voce del menu, differenziare le varie tipologie di pagina presenti nel sito.
Un id viene anche attribuito alle singole voci del menu: per comodità e convenzione, questo è ottenuto anteponendo una "m" (che sta per menu) ai possibili id attribuibili al body.
Come si può notare in questo caso non ci sono span aggiuntivi nell'HTML. La tecnica di image replacement che useremo, infatti, non richiede markup addizionale.
Le immagini che compongono il menu
Prima di procedere con il foglio di stile, diamo uno sguardo ad una delle immagini che compongono il menu. Ho aggiunto un bordino rosso per evidenziare il fatto che si tratta di un'immagine unica:
È larga 120 pixels e alta 90 e racchiude i tre stati della voce "HOME" in tre strisce orizzontali di 30 pixels ciascuna. Dall'alto verso il basso abbiamo lo stato normale, quello hover e quello attivo. Allo stesso modo sono realizzate le altre voci del menu, in cui cambia solo il testo. Per prepararle, vi sarà molto comodo l'uso di un software di grafica che disponga dei livelli: una volta preparato lo sfondo basterà infatti sistemare le scritte su un livello soprastante, magari aiutandosi con una griglia per ottenere la precisione al pixel necessaria per una buona resa.
Il foglio di stile
Arriviamo al CSS: nell'insieme non è complicato, ma presenta alcuni hack e dichiarazioni aggiuntive necessarie per estendere al massimo la compatibilità tra i browser ed evitare il flickering su IE. Per prima cosa lavoriamo sulla lista: attribuiamo le dimensioni, eliminiamo i marcatori, il margin e il padding:
div#nav ul{width: 600px;line-height: 3px; list-style-type:
none;
margin: 0;padding: 0}
Da notare che l'istruzione line-height: 3px; è stata necessaria per mantenere la compatibilità con IE 5 Mac, che presentava un bug nella resa del menu orizzontale.
A questo punto lavoriamo sui list-item e sui link. Dopo aver rimosso margini e padding dagli li, bisognerà procedere a renderli float e attribuire le dimensioni. Per comodità, risparmio di peso del CSS e compatibilità (ancora una volta!) per IE Mac, una parte della regola viene anche attribuita ai link usando il raggruppamento parziale:
div#nav li{margin: 0;padding: 0}
div#nav li, div#nav a{float: left;width: 120px;height: 30px}
Ora arriviamo alla parte fondamentale. Ci serve una tecnica di image replacement (cfr. Articolo «Le tecniche di Image Replacement>»). Per questa versione di menu ho deciso di optare per una tecnica che non richiedesse markup aggiuntivo, abbandonando quindi la cover-up span. È abbastanza diffusa ultimamente una tecnica che combina l'height a zero e il text-indent negativo. Questa tecnica si rivela robusta e accessibile a screen reader e browser testuali. Purtroppo però, a differenza della cover-up span, non funziona a immagini disabilitate. Vediamola:
div#nav a{text-indent: -9000px;text-decoration: none;padding: 30px 0 0 0;
overflow: hidden; height: 0px !important; height /**/:30px; /* per IE5*/ }
Per la riuscita della tecnica è importante che le due dichiarazioni che riguardano l'altezza seguano l'ordine riportato e che l'altezza effettiva (in questo caso pari a 30pixel, serve per Internet Explorer 5.x data la sua errata interpretazione del box model) venga dichiarata con un commento vuoto (/**/)che precede i due punti e a cui segue uno spazio.
Adesso dichiariamo gli sfondi per i link: per evitare il flickering su Internet Explorer è sufficiente specificare lo stesso sfondo dei link anche sul list-item. Ecco le regole:
li#mhome, li#mhome a{background-image: url(home.jpg)}
li#mgrafica, li#mgrafica a{background-image: url(grafica.jpg)}
li#mweb, li#mweb a{background-image: url(web.jpg)}
li#mcss, li#mcss a{background-image: url(css.jpg)}
li#mjs, li#mjs a{background-image: url(js.jpg)}
Arriviamo ora allo stato hover. Per ciascuna voce del menu basterà giocare sul background-position, mostrando così la sezione dell'immagine relativa. Per sistemare definitivamente il problema flickering su IE, accorpiamo la regola anche per i list-item:
#nav li, #nav a:hover{background-position: 0 -30px}
Come ultimo passo, non ci resta che specificare le regole per gli stati attivi. È questo il passo concettualmente più importante del menu: il meccanismo può rivelarsi sottile e complicato, ma è decisamente potente. È una combinazione di HTML e CSS. Abbiamo attribuito ad ogni singola pagina un id al body, di modo da poter indicarne la voce del menu di appartenenza, e un id anche ad ogni voce del menu. Non ci resta che combinarli grazie ai CSS, sfruttando il selettore discendente. In questo caso si tratta di attribuire tramite CSS la background-position per ciascuna voce attiva del menu a cui corrisponde il relativo id del body. Una regola per ogni voce del menu, quindi. Accorperemo tutto in unica regola con, in questo caso, cinque selettori:
body#home li#mhome a, body#grafica li#mgrafica a, body#web li#mweb a,
body#css li#mcss a,body#js li#mjs a{ background-position: 0 -60px}
Il nostro menu è così ultimato. Per adattarlo alle vostre esigenze vi basterà preparare le immagini, modificare se necessario le dimensioni e le posizioni del background e cambiare gli id di modo che siano rappresentativi per le voci del menu.
La versione verticale del menu
Come sempre, i fogli di stile ci permettono un alto livello di personalizzazione: usando lo stesso codice HTML è infatti possibile ottenere un menu verticale. A parte i nomi delle immagini e la dimensione del menu, le modifiche al foglio di stile sono veramente minime: è bastato infatti rendere sia list-item che i link come elementi block-level. Vediamo il CSS per intero:
body{background: #FFF}
div#nav{margin: 50px 0 0 50px}
div#nav ul{width: 120px;height: 150px;list-style-type: none;
margin: 0;padding: 0}
div#nav li{margin: 0;padding: 0}
div#nav li,div#nav a{display: block;width: 120px;height: 30px}
div#nav a{text-indent: -9000px;text-decoration: none;padding: 30px 0 0 0;
overflow: hidden; height: 0px !important; height /**/:30px}
li#mhome, li#mhome a{background-image: url(home2.jpg)}
li#mgrafica, li#mgrafica a{background-image: url(grafica2.jpg)}
li#mweb, li#mweb a{background-image: url(web2.jpg)}
li#mcss, li#mcss a{background-image: url(css2.jpg)}
li#mjs, li#mjs a{background-image: url(js2.jpg)}
#nav li, #nav a:hover{background-position: 0 -30px}
body#home li#mhome a, body#grafica li#mgrafica a, body#web li#mweb a,
body#css li#mcss a,body#js li#mjs a{background-position: 0 -60px}
Esempi e immagini sono contenuti nello zip allegato all'articolo.
Abbiamo visto una versione leggermente migliorata di menu con image replacement e rollover via css. Presenterò ora una tecnica abbastanza recente che si rivela potente, versatile e vantaggiosa: usa infatti un'unica immagine per un intero menu di navigazione.
Continuiamo i nostri esperimenti con i menu grafici. Abbiamo visto un menu che combina fast CSS rollover e image replacement. Per realizzarlo è necessario preparare un'immagine che racchiude i tre stati del link per ogni voce del menu. Si può compiere un ulteriore passo avanti: ci ha pensato Dave Shea in un interessante articolo presentato su Alistapart, CSS Sprites.
Si tratta di usare un'unica immagine per un intero menu. Dopo l'uscita dell'articolo sono comparse diverse varianti, tutte accomunate dal fatto che la grafica del menu è concentrata in un solo file.
La prima è Navigation Matrix: è un menu a tab sovrapposti in cui il tab attivo "sconfina" nel tab alla sua sinistra. La tecnica CSS di per sè non è complessa, lo è invece la metodologia con cui è stata preparata l'immagine. Altra variante sul tema è the Bend, una tecnica per ottenere un menu fatto ad arco. Con un menu costituito da una sola immagine i vantaggi sono molti: una maggiore facilità nell'elaborazione grafica, maggiori potenzialità e meno limiti e soprattutto meno carico sul server. Un'immagine sola per un intero menu pesa sicuramente meno della decina o più che la compongono singolarmente. Inoltre, richiede al server un solo trasferimento. Vedremo in questo articolo due possibili varianti della navigation matrix.
Menu Orizzontale con Navigation Matrix
La tecnica che presenterò qui è una versione semplificata della versione originale, ma il termine rende decisamente l'idea: matrice di navigazione. Anzitutto vediamo l'esempio che ho preparato. Sono cinque pagine, in cui ad ognuna di esse corrisponde una voce attiva del menu. Prima di cominciare con il codice, vediamo l'unica immagine che compone il menu:
Si tratta di una matrice composta da 15 celle, disposte su 5 colonne (una per voce del menu) per 3 righe (una per stato). Dall'alto verso il basso abbiamo lo stato normale, quello hover e quello attivo. Ogni cella del menu ha dimensioni 90 per 30 pixel. Ora diamo uno sguardo all'HTML. Anche in questo caso si tratta di una lista ordinata e, come negli esempi dello scorso articolo, viene attribuito un id al body (per poter evidenziare la voce attiva del menu) così come ad ogni list-item:
<body id="home">
<div id="nav">
<ul>
<li id="mhome"><a href="navmatrix1.html">Home</a></li>
<li id="mprod"><a href="navmatrix2.html">Prodotti</a></li>
<li id="mserv"><a href="navmatrix3.html">Servizi</a></li>
<li id="mport"><a href="navmatrix4.html">Portfolio</a></li>
<li id="mcont"><a href="navmatrix5.html">Contatti</a></li>
</ul>
</div>
</body>
Ora vediamo come i CSS siano in grado di trasformare una semplice lista non ordinata in un menu grafico orizzontale con rollover e preload. Anzitutto lavoriamo sulla lista di navigazione. Attribuiamo le dimensioni necessarie a contenere l'intero menu ed eliminiamo bullet, margin e padding. È fondamentale, inoltre, per evitare il flickering di Internet Explorer, attribuire l'immagine del menu relativa allo stato hover. Ecco la regola:
div#nav ul{width: 450px;height: 30px;overflow: hidden;
list-style-type: none;margin: 0;padding: 0;
background:url(h-matrix.jpg) no-repeat 0 -30px}
A questo punto lavoriamo sui list-item e sui link. Dopo aver rimosso margini e padding dai li, bisognerà procedere a renderli float e attribuire le dimensioni:
div#nav li{margin: 0;padding: 0}
div#nav li,div#nav a{float: left;width: 90px;height: 30px}
Ora dovremmo applicare l'image replacement sui link. Anche in questo caso, come nello scorso appuntamento, usiamo una tecnica che combina il text-indent negativo e l'height a zero:
div#nav a{text-indent: -9000px;text-decoration: none;padding: 30px 0 0 0;
overflow: hidden; height: 0px !important; height /**/:30px;
background-image: url(h-matrix.jpg)}
Avendo già specificato dimensioni e immagine di sfondo per i link, non ci resta che specificare la background-position per i tre stati di ciascun link. Queste le tre regole per lo stato normale, hover e attivo della voce relativa alla home page:
li#mhome a{background-position: 0px 0px}
li#mhome a:hover{background-position: 0 -30px}
body#home li#mhome a{background-position: 0 -60px}
Ricordo che i valori della proprietà background-position si riferiscono rispettivamente all'asse orizzontale (x) e all'asse verticale (y), e che una coordinata negativa sull'asse x sposta lo sfondo verso sinistra, verso l'alto sulla y. Da notare il selettore discendente per lo stato attivo: nell'HTML abbiamo attribuito, nella pagina relativa alla home page, un id=home al body.
Analogamente, specifichiamo le regole necessarie agli altri link:
li#mprod a{background-position: -90px 0px}
li#mprod a:hover{background-position: -90px -30px}
body#prod li#mprod a{background-position: -90px -60px}
li#mserv a{background-position: -180px 0px}
li#mserv a:hover{background-position: -180px -30px}
body#serv li#mserv a{background-position: -180px -60px}
li#mport a{background-position: -270px 0px}
li#mport a:hover{background-position: -270px -30px}
body#port li#mport a{background-position: -270px -60px}
li#mcont a{background-position: -360px 0px}
li#mcont a:hover{background-position: -360px -30px}
body#cont li#mcont a{background-position: -360px -60px}
Il foglio di stile è così ultimato: rivediamo il risultato.
Navigation Matrix con posizionamenti assoluti
Finora nella serie dei menu grafici e semigrafici abbiamo visto per ogni tipologia di menu la versione orizzontale e verticale. In questo caso farò un'eccezione, trascurando la "classica" versione verticale. Credo che ne valga la pena: vedremo una versione che usa i posizionamenti assoluti. Usare un'unica immagine per un intero menu aumenta davvero le possibilità di creazione grafica, e i posizionamenti assoluti sono l'ideale per una tecnica simile: potremo realizzare infatti dei menu ad arco, circolari, a onda, a mappa ecc... proprio come se fossero immagini mappate con effetto rollover.
Vediamo subito il prossimo esempio. Si tratta di un menu un po' particolare, in cui le singole voci seguono la "s" che lo delimita spazialmente. L'unica immagine che compone il menu è, in versione leggermente rimpicciolita per questioni di spazio, la seguente:
Questo è il link al file a dimensioni originali, che è 600x250 pixels. Per comodità nel realizzarlo, in questo caso ho disposto i tre stati del menu orizzontalmente: da sinistra verso destra abbiamo lo stato normale, lo stato hover e lo stato attivo, in tre aree larghe 200pixels.
l'HTML è identico all'esempio precedente: viene attribuito un id al body e uno a ciascun li.
Vediamo subito il CSS. Per prima cosa il div che contiene il menu di navigazione: nell'esempio la regola non è presente, ma in una pagina reale che non contiene solo il menu andrà reso float o posizionato assolutamente. Ora la lista di navigazione: attribuiamo dimensioni, eliminiamo il marcatore, i margini e il padding. Attribuiamo come sfondo l'immagine del menu relativa alla porzione in stato hover (questo è necessario per evitare il flickering di IE) e infine lo dichiariamo position:relative: in questo modo potremo infatti referenziare le singole voci del menu al suo interno grazie al posizionamento assoluto:
div#nav ul{position:relative;width: 200px;height: 250px;overflow: hidden;
list-style-type: none;margin: 0;padding: 0;
background:url(matrix.jpg) no-repeat -200px 0}
A questo punto i list-item: nella prossima regola metteremo tutte le dicharazioni comuni a tutte le voci del menu:
div#nav li{position: absolute;height: 30px;margin: 0;padding: 0}
Ora i link: useremo anche qui la tecnica di image replacement che abbiamo adottato negli ultimi esempi, dichiarandoli in questo caso display:block. Ecco la regola:
div#nav a{display: block;text-indent: -9000px;text-decoration: none;
padding: 30px 0 0 0;overflow: hidden;height: 0px !important;
height /**/:30px;background-image: url(matrix.jpg)}
Per ciascuna voce del menu andremo quindi a completare la regola generica sui list-intem vista sopra: dichiareremo quindi le coordinate del posizionamento assoluto e larghezza. Per rilevare questi valori vi verrà utile lo stesso programma con cui avrete realizato l'immagine del menu: i più comuni programmi di grafica sono infatti in grado di riportare coordinate e dimensioni di una selezione. Per ogni link andranno specificati lo stato normale, lo stato hover e quello attivo, intervenedo sul background-position: da notare che le coordinate dello stato normale corrispondono alla posizione del list-item che lo contiene, mentre quelle degli altri due stati sono ottenute traslando la coordinata "x" in questo caso di 200 e 400 pixel rispettivamente, ossia proprio la larghezza di una singola porzione del menu. Ecco quindi le regole necessarie:
li#mhome{width: 120px;left: 60px;top: 0}
li#mhome a{background-position: -60px 0}
li#mhome a:hover{background-position: -260px 0}
body#home li#mhome a{background-position: -460px 0}
li#mprod{width: 90px;left: 30px;top: 40px}
li#mprod a{background-position: -30px -40px}
li#mprod a:hover{background-position: -230px -40px}
body#prod li#mprod a{background-position: -430px -40px}
li#mserv{width: 70px;left: 50px;top: 90px}
li#mserv a{background-position: -50px -90px}
li#mserv a:hover{background-position: -250px -90px}
body#serv li#mserv a{background-position: -450px -90px}
li#mport{width: 90px;left: 30px;top: 140px}
li#mport a{background-position: -30px -140px}
li#mport a:hover{background-position: -230px -140px}
body#port li#mport a{background-position: -430px -140px}
li#mcont{width: 90px;left: 0;top: 190px}
li#mcont a{background-position: 0 -190px}
li#mcont a:hover{background-position: -200px -190px}
body#cont li#mcont a{background-position: -400px -190px}
Il CSS è così ultimato: non ci resta che rivedere l'esempio. Immagini e file degli esempi sono tutti presenti nello zip allegato.
Gli esempi sono stati testati con successo sui seguenti browser:
- Safari 1.2.3 (v125.9) - Mac
- Internet Explorer 5.2 - Mac
- Firefox 0.9 - Mac
- Opera 7.52 - Mac
- Internet Explorer 5, 5.5, 6.0 - Windows
- Firefox 0.9 - Windows
- Opera 7.02 - Windows
Note finali
Gli ultimi due menu che abbiamo visto in questo articolo hanno una buona compatibilità cross-browser. Ho notato un piccolissimo problema di flickering con IE6 solo sul link attivo di ogni pagina. Per riprodurre il fenomeno vi basterà modificare le impostazioni di IE come segue. Dal menu Strumenti>Opzioni Internet>Impostazioni dei file temporanei internet>Ricerca versioni più recenti delle pagine memorizzate > selezionare l'opzione All'apertura della pagina. Con qualsiasi altra opzione settata il flickering non avviene, e comunque l'impostazione di default sul browser è Automaticamente. In questo caso è quasi impercettibile, e la voce attiva del menu "sfarfalla" per un attimo tra lo stato hover e quello attivo se ci si passa sopra con il mouse. Il fenomeno in questo caso non forza il ricaricamento dell'immagine del menu, quindi non causa traffico sul server. C' è da dire che difficilmente un utente si troverà a passare il mouse sopra una voce di menu già attiva, e quindi anche per l'utente non risulta particolarmente fastidioso.
Volendo sistemarlo, le possibili soluzioni sono due.
Nel primo caso, far si che anche lo stato attivo risenta dello stato hover, come in the Bend. Questa soluzione non mi piace molto: lo stato attivo a parer mio deve essere persistente e quindi non subire rollover. Inoltre, come vedremo tra poco, la tecnica dal punto di vista del CSS è molto simile alla versione originale di Navigation Matrix, e implica la moltiplicazione delle regole.
L'altra soluzione è anzitutto grafica: per ogni voce di menu dovremo realizzare una riga (o colonna) che rappresenta una voce attiva e le altre in stato hover, più (almeno) una riga con tutti gli stati normali, come per esempio in Navigation Matrix. Questo determina un aumento notevole delle dimensioni dell'immagine per il menu; inoltre anche il CSS si fa più pesante e ridondante: quello che bisognerà fare è procedere a "moltiplicare" ogni possibile id del body con tutte le voci del menu in stato normale e stato hover. Per un menu a cinque voci come quelli qui presentati,quindi, saranno necessarie ben 50 regole CSS (più le 5 per lo sfondo all'ul per evitare il flickering), contro le 15 o le 20 dei menu che abbiamo visto. La tecniche qui presentate richiedono infatti un numero di regole per gli stati dei link pari al triplo o al quadruplo del numero di voci del menu; una tecnica come la versione originale di navigation matrix richiede invece il doppio delle voci del menu moltiplicate al quadrato. Anche questa soluzione è quindi sconsigliata, per il conseguente aumento delle dimensioni dell'immagine e del foglio di stile. Non ci resta quindi che accettare la tecnica con un piccolo difetto.
Nella ricerca del pieno supporto dei fogli di stile, come sempre lo sviluppatore si trova di fronte ai compromessi. Alla prossima.