L'uso degli sprites CSS per la realizzazione di menu grafici (e non solo) è da tempo una tecnica consolidata e consigliata in tutti i vademecum per l'ottimizzazione del caricamento delle pagine web. Dal momento che viene adoperata una sola immagine per definire tutti gli stati del menu, infatti, gli sprites consentono di ridurre notevolmente il numero di richieste HTTP.
Qualche tempo fa, lo stesso creatore della tecnica, Dave Shea, ha promosso una revisione che preveda un'integrazione con Javascript nell'articolo CSS Sprites2: è l'ora di Javascript.
Alla base di questa revisione un'esigenza fondamentale: sfruttare le funzionalità di animazione offerte dai vari framework Javascript come jQuery per dare più vita ai nostri menu.
Ma l'uso di soluzioni basate su jQuery va anche incontro ad un'altra esigenza: quella di semplificare la scrittura del codice CSS necessario all'implementazione della tecnica. È quanto promette un plugin come Autosprites.
Un esempio con i CSS
Quando si realizza un menu basato sugli sprites CSS, prima di mettere mano al codice, sono necessarie due operazioni preliminari.
Innanzitutto bisognerà preparare nel nostro programma di grafica preferito l'immagine che useremo come base. Essa dovrà contenere almeno due varianti di uno stesso elemento del menu, quella per lo stato 'normale' e quella per l'hover. Un'aggiunta frequente è quella di una terza variante, quella per lo stato 'attivo'.
È poi necessario prendere un po' di misure, ovvero calcolare precisamente le dimensioni di ciascuna voce del menu, in larghezza e altezza. Infatti, l'implementazione finale è basata sulla proprietà background-position
: senza conoscere con esattezza quei dati relativi alle dimensioni, nel dichiarare le coordinate andremmo incontro ad un frustrante 'prova e ricarica' fino a quando non si trovano le posizioni giuste.
Per mostrare come si usa il plugin Autosprites, siamo partiti da questo esempio che usa solo i CSS, spiegato in maniera dettagliata nell'articolo Menu grafici con rollover e preload via CSS.
Base del menu è questa immagine:
Si tratta di una vera e propria griglia, con ciascuna voce larga 90px e alta 30px. Le varianti sono tre, per gli stati normale, hover e attivo. Le dimensioni totali sono di 450x90px.
Se si osserva il codice CSS, si percepisce la complessità dell'operazione, specie nella parte in cui bisogna calcolare le coordinate di background-position
. Nel nostro caso, tra l'altro, tutto è semplificato dal fatto di essere partiti da una griglia molto semplice, ma in altre circostanze, con voci di menu di larghezza disuguale, le cose si complicano:
div#nav{margin: 50px 0 0 50px}
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}
div#nav li{margin: 0;padding: 0}
div#nav li,div#nav a{float: left;width: 90px;height: 30px}
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)}
li#mhome a{background-position: 0px 0px}
li#mhome a:hover{background-position: 0 -30px}
li#mhome a.active{background-position: 0 -60px}
li#mprod a{background-position: -90px 0px}
li#mprod a:hover{background-position: -90px -30px}
li#mprod a.active {background-position: -90px -60px}
li#mserv a{background-position: -180px 0px}
li#mserv a:hover{background-position: -180px -30px}
li#mserv a.active{background-position: -180px -60px}
li#mport a{background-position: -270px 0px}
li#mport a:hover{background-position: -270px -30px}
li#mport a.active{background-position: -270px -60px}
li#mcont a{background-position: -360px 0px}
li#mcont a:hover{background-position: -360px -30px}
li#mcont a.active{background-position: -360px -60px}
Bene, ecco a cosa si riduce il CSS necessario ad ottenere lo stesso effetto, con in più una semplice animazione, usando il plugin Autosprites:
#nav {position: absolute; left: 0; width: 450px; height: 30px; background: url('h-matrix.jpg') no-repeat;}
#nav li {position: absolute; left: 0; height: 30px; }
#nav #mhome { width: 90px; left: 0px; }
#nav #mprod { width: 90px; left: 90px; }
#nav #mserv{ width: 90px; left: 180px; }
#nav #mport { width: 90px; left: 270px; }
#nav #mcont { width: 90px; left: 360px; }
#nav li a { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 72px; text-indent: -9999em; }
Ecco la demo. A questo punto possiamo andare ad analizzare come funziona il nostro plugin.
Usare Autosprites
Nell'esempio siamo partiti da una semplicissima struttura HTML:
<ul id="nav">
<li id="mhome"><a href="#">Home</a></li>
<li id="mprod" class="active"><a href="#">Prodotti</a></li>
<li id="mserv"><a href="#">Servizi</a></li>
<li id="mport"><a href="#">Portfolio</a></li>
<li id="mcont"><a href="#">Contatti</a></li>
</ul>
Una lista non ordinata con id #nav
, cinque item di menu, uno dei quali con la classe active
che lo connota come quello attualmente attivo.
Prima di passare al Javascript, dobbiamo tornare al CSS:
#nav {position: absolute; left: 0; width: 450px; height: 30px; background: url('h-matrix.jpg') no-repeat;}
#nav li {position: absolute; left: 0; height: 30px; }
#nav #mhome { width: 90px; left: 0px; }
#nav #mprod { width: 90px; left: 90px; }
#nav #mserv{ width: 90px; left: 180px; }
#nav #mport { width: 90px; left: 270px; }
#nav #mcont { width: 90px; left: 360px; }
#nav li a { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 30px; text-indent: -9999em; }
Operando con Autosprites, si comincia col definire una regola per la lista che contiene il menu. Le parti fondamentali riguardano l'inserimento come sfondo non ripetuto dello sprite (url('h-matrix.jpg')
; la definizione delle dimensioni (450px è la larghezza totale, 30px l'altezza della prima riga, quello per lo stato 'normale' del menu).
Subito dopo definiamo una regola generica per i li
, anch'essi posizionati assolutamente e con altezza pari a 30px.
Per finire le regole relative ai singoli item del menu. Per ciascuno non è necessario, come nell'esempio basato sui soli CSS, specificare lo spostamento dello sfondo! Basta inserire il valore della larghezza (width
) e lo spostamento in pixel rispetto al lato sinistro. Il primo item avrà quindi come valore 0, il secondo 90px, il terzo 180, etc.
L'ultima regola serve a definire il comportamento dei link.
Preparato il terreno, possiamo inserire il codice Javascript. Prima del tag body
di chiusura abbiamo:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="autosprites.min.js"></script>
<script>
$(document).ready(function(){
$('#nav').autosprites({
offset: '30px',
activeState: true,
activeClass: 'active',
activeSprites: true
});
});
</script>
Carichiamo prima jQuery, poi il plugin, quindi la breve sezione di inizializzazione con il metodo autosprites
applicato alla lista con id #nav
.
Il parametro fondamentale è offset: '30px'
. Con questa istruzione diciamo allo script: quando si passa il mouse sul menu, sposta lo sfondo dell'immagine di 30px verso l'alto.
Il nostro menu sarebbe già così perfettamente funzionante, ma per replicare nei dettagli l'esempio di partenza, abbiamo aggiunto una parte per lo stato attivo:
activeState: true,
activeClass: 'active',
activeSprites: true
L'opzione activeState
va settata su true
, ma così sarà usata per lo stato attivo l'immagine di hover. Con activeClass
facciamo riferimento alla classe presente nel codice HTML che designa lo stato attivo. Con activeSprites
stabiliamo che lo script deve usare per lo stato attivo la sezione dello sprite specifica (la terza riga per inntenderci).
Per ulteriori approfondimenti e opzioni si può fare riferimento alla documentazione ufficiale e agli esempi forniti dall'autore del plugin.
Le demo viste nell'articolo sono disponibili per il download.