L’articolo (in lingua inglese) proviene da Devthought.com ed è stato tradotto e riprodotto per gentile concessione dell’autore Guillermo Rauch.

Quando si deve decidere come creare la parte di navigazione di un sito web, la prima cosa a cui potreste pensare è quella di utilizzare una lista che può essere stilizzata come tab. Ultimamente questo tipo di menu di navigazione sono ovunque, proprio perchè molta gente crede che renda il loro sito più compatibile con il web 2.0. Personalmente io penso che risultino essere semanticamente migliori e più accessibili.

Visualizza l’esempio

In questo articolo esporrò la creazione di una barra di navigazione con alcuni effetti Javascript che sicuramente impressioneranno i vostri amici. Grazie alla strepitosa libreria Mootools, che oltre è grande solo 1,5 kb. Non solo, ma è anche cross browser ( testato su Internet Explorer 6, Internet Explorer 7, Firefox, Safari) e accessibile.

Introduzione

Ogni volta che so che dovrò usare Javascript per il comportamento o l’aspetto di qualcosa, provo a usare un markup e mi assicuro di renderlo perfettamente con il Javascript disabilitato. Per illustrare questo punto, immagina di voler creare un elemento più largo sul rollover. La proprietà Javascript che cambia è widht: , così sono sicuro che il mio stile funziona quando modifico a caso tale proprietà.

Per questo menu, poiché avremo un elenco mobile che agisce da sfondo , dovremo prima assicurarci che usando il CSS possiamo liberamente muoverlo e che non andrà a interferire con la visualizzazione del menu. Se non controlli questo, quando andrai a codificare il JS e troverai un bug, ti chiederai se questo è causato dal CSS, dal Javascript oppure dal browser.

Mettilo in evidenza

Proprio come ogni altro menu di navigazione, useremo una lista disordinata con alcuni punti fermi:

[code lang=”html”]
<div id="fancymenu">
<ul>
<li class="current" id="menu_home"><a href="#">Home</a></li>
<li id="menu_plantatree"><a href="#">Plant a tree</a></li>
<li id="menu_travel"><a href="#">Travel</a></li>
<li id="menu_rideanelephant"><a href="#">Ride an elephant</a></li>
</ul>
</div>
[/code]

Questo è il fondamento per una struttura semanticamente corretta e una navigazione degradabile facilitata.

Lo stile CSS

Come ho detto prima, è fondamentale creare un CSS perfetto e cross browser.

Il primo problema che dobbiamo affrontare è l’impossibilità di usare, con le attuali specifiche CSS supportate dalla maggior parte dei browser, la proprietà background per il box arrotondato che segue il movimento del mouse. Questo ci costringe ad aggiungere un nuovo elemento LI che si comporterà come il background mobile.

Ora andremo a disporre position:relative; sulla lista, e position:absolute; sull’oggetto mobile, così sarà facile muoverlo con il Javascript tra i contorni del menu. Se non capisci bene come funziona, ti consiglio di leggere questo articolo sui posizionamenti CSS. Capirai che se utilizziamo semplicemente position:absolute; sul background, dovremmo poi fare dei calcoli inutili e complicati per posizionarlo correttamente con il Javascript.

Quindi, questo è il codice che abbiamo finora:

[code lang=”css”]
#fancymenu {
position: relative;
height: 29px;
width: 421px;
background: url(‘images/bg.gif’) no-repeat top;
padding: 15px;
margin: 10px 0;
overflow: hidden;
}

#fancymenu ul {
padding: 0;
margin: 0;
}

/* Don’t apply padding here (offsetWidth will differ in IE)
If you need padding add it to the child anchor */
#fancymenu ul li {
float: left;
list-style: none;
}
#fancymenu ul li a {
text-indent: -500em;
z-index: 10;
display: block;
float: left;
height: 30px;
position: relative;
overflow: hidden;
}
[/code]

Fin ora è abbastanza facile, ed ho incluso alcuni commenti per le parti difficili. La proprietà text-indent è utilizzata per nascondere il testo senza l’aggiunta di un altro markup, e per mantenerlo accessibile.

Ora dobbiamo aggiungere le immagini in background per ogni link:

[code lang=”css”]
#menu_home a {
width: 59px;
background: url(‘images/menu_home.png’) no-repeat center !important;
background: url(‘images/menu_home.gif’) no-repeat center; // ie!
}

#menu_plantatree a {
width: 119px;
background: url(‘images/menu_plantatree.png’) no-repeat center !important;
background: url(‘images/menu_plantatree.gif’) no-repeat center;
}

#menu_travel a {
width: 70px;
background: url(‘images/menu_travel.png’) no-repeat center !important;
background: url(‘images/menu_travel.gif’) no-repeat center;
}

#menu_rideanelephant a {
width: 142px;
background: url(‘images/menu_rideanelephant.png’) no-repeat center !important;
background: url(‘images/menu_rideanelephant.gif’) no-repeat center;
}
[/code]

Nella seguente sezione vedrai perché usiamo le immagini .gif per Internet Explorer utilizzando l’hack !important.

Lo sfondo in movimento

Come abbiamo detto, c’è un LI che si muove in un livello più basso e si allunga per prendere la forma di ogni elemento. Per la sua struttura, useremo qualcosa di simile alla tecnica delle Sliding Doors, ma senza testo.

Il suo markup sarebbe il seguente:

[code lang=”html”]<li class="background"><div class="left">&nbsp;</div></li>[/code]

Poiché questo non presenta nessun ruolo semantico nella lista, andremo ad includerlo nel Javascript. Certamente, per testare, puoi includerlo manualmente e poi rimuoverlo. Questo è lo stile:

[code lang=”css”]
#fancymenu li.background {
background: url(‘images/bg_menu_right.png’) no-repeat top right !important;
background: url(‘images/bg_menu_right.gif’) no-repeat top right;
z-index: 8;
position: absolute;
visibility: hidden;
}

#fancymenu .background .left {
background: url(‘images/bg_menu.png’) no-repeat top left !important;
background: url(‘images/bg_menu.gif’) no-repeat top left;
height: 30px;
margin-right: 9px; /* 7px is the width of the rounded shape */
}
[/code]

L’uso di questa tecnica è una delle principali ragioni per cui non usiamo i filtri per visualizzare le png con Internet Explorer. Con tali filtri non si può decidere la posizione del background, e farebbero visualizzare l’angolo destro sulla parte sinistra. Leggi questo articolo sulle limitazioni dell’hack per le png per saperne di più. Un’altra ragione è che la Microsoft fa aggiornare automaticamente ad Internet Explorer 7, il quale supporta perfettamente le png.

Tieni bene a mente che quando esporti le .gif dovrai usare il sistema Matte per le trasparenze di modo da abbinarlo al colore di background, altrimenti tutto apparirà scadente. Questa immagine illustra come dovrebbe risultare la tua immagine:

Comparazione gid e png

Scrivere lo script

Grazie al nostro CSS, il Javascript risulta essere molto corto e semplice. Il suo ruolo è limitato all’aggiunta dell’extra markup per il background, e inoltre è responsabile degli effetti di restringimento e del movimento.

Poi avremo bisogno del Fx.Style.js, del Dom.js di Mootool, e delle loro dipendenze. Per l’esempio di questo articolo ho usato anche un effetto transizione trovato nel pacchetto Fx.Transitions (ricorda che l’effetto transitino è quello che fa muovere il background). E’ codificato sotto forma di una Class, così è possibile mettere più menu all’interno di una stessa pagina.

[code lang=”javascript”]
var SlideList = new Class({
initialize: function(menu, options) {
this.setOptions(this.getOptions(), options);

this.menu = $(menu), this.current =
this.menu.getElement(‘li.current’);

this.menu.getElements(‘li’).each(function(item){
item.addEvent(‘mouseover’, function(){
this.moveBg(item); }.bind(this));
item.addEvent(‘mouseout’, function(){
this.moveBg(this.current); }.bind(this));
item.addEvent(‘click’, function(event){
this.clickItem(event, item); }.bind(this));
}.bind(this));

this.back = new
Element(‘li’).addClass(‘background’).adopt(new
Element(‘div’).addClass(‘left’)).injectInside(this.menu);
this.back.fx = this.back.effects(this.options);
if(this.current) this.setCurrent(this.current);
},

setCurrent: function(el, effect){
this.back.setStyles({
left: (el.offsetLeft)+’px’, width:
(el.offsetWidth)+’px’});
(effect) ? this.back.effect(‘opacity’).set(0).start(1) :
this.back.setOpacity(1);
this.current = el;
},

getOptions: function(){
return {
transition: Fx.Transitions.sineInOut,
duration: 500, wait: false,
onClick: Class.empty
};
},

clickItem: function(event, item) {
if(!this.current) this.setCurrent(item, true);
this.current = item;
this.options.onClick(new Event(event), item);
},

moveBg: function(to) {
if(!this.current) return;
this.back.fx.custom({
left: [this.back.offsetLeft, to.offsetLeft],
width: [this.back.offsetWidth, to.offsetWidth]
});
}
});

SlideList.implement(new Options);
[/code]

Finalmente, è ora di cominciare. Creiamo l’oggetto disponendo l’id e le opzioni desiderate. L’esempio seguente mostra come fare quando il DOM della pagina è caricato.

[code lang=”javascript”]
window.addEvent(‘domready’, function() {
new SlideList($E(‘ul’, ‘fancymenu’), {transition:
Fx.Transitions.backOut, duration: 700, onClick: function(ev,
item) { ev.stop(); }});
});
[/code]

Lo script cerca prima l’elemento a cui è riferita la classe corrente. Se la trova, posiziona il background dietro di essa. Se non la trova, aspetta finché l’utente non effettua il primo click per disporre così la classe ‘current’. Questo risulta molto utileper quei menu che deve selezionare l’utente, piuttosto che nei menu con i link a URL veri e propri.

Vi sono delle opzioni del onClick, che richiama una funzione nell’oggetto Event e cliccando sull’elemento si fanno scattare i parametri per quell’oggetto. Così si possono cambiare la durata dell’effetto, la transizione, ecc.