Realizzazione con i CSS di una barra di navigazione laterale con sottomen¨ che si aprono al passaggio del mouse

In questo tutorial realizzeremo un men¨ verticale, che potrÓ quindi essere inserito in una barra di navigazione laterale (a destra o a sinistra del contenuto principale della pagina). Passando con il mouse su ciascuna voce del men¨, si deve aprire un sottomen¨ (anch'esso verticale) relativo alla voce stessa, come mostrato nella figura seguente:

Men¨ verticale con apertura del sottomenu al passaggio del mouse

Creazione della struttura HTML

Nota: questa sezione della pagina riproduce esattamente la sezione con lo stesso nome che si trova nel tutorial "Realizzazione di menu a tendina con i CSS". Se hai giÓ svolto quel tutorial, quindi, ti consiglio di passare alla sezione "Creazione del CSS".

Dal menu che vedi in figura, avrai capito che come esempio utilizzeremo delle voci adatte ad un sito di acquisti online. Le voci sono classificate per categorie di prodotti (Electronics, Fashion, Home & Garden, Deals & Gifts, Collectibles & Art) in un primo livello di menu, quindi in sottocategorie pi¨ specifiche in un secondo livello di menu.

Costruiamo innanzitutto la struttura semantica del menu nel nostro file HTML. L'intero menu Ŕ compreso in un nodo di navigazione delimitato dal tag <nav>. All'interno di questo menu si trova una lista <ul>, composta dalle voci di menu di primo livello, ciascuna delle quali contiene a sua volta il relativo menu di secondo livello.

Iniziamo con il costruire il menu principale (all'interno del tag <body>, ovviamente). Ecco la struttura HTML:

Struttura HTML del men¨ principale

I codici &amp; sono l'"entitÓ" HTML utilizzata per rappresentare il simbolo & ("e commerciale", in inglese "ampersand").

Ogni elemento del menu principale, per˛, deve contenere, oltre ad una delle categorie principali (Electronics, Fashion, Home & Garden, Deals & Gifts, Collectibles & Art), anche il sottomenu corrispondente a ciascuna di esse. Ogni elemento <li> della struttura precedente, quindi, deve contenere a sua volta una lista <ul>. Ecco come ci˛ viene realizzato tramite il codice HTML:

Struttura HTML del men¨ principale con i sottomen¨

Nella figura precedente, si noti che abbiamo inserito anche un elemento <div>, che ospiterÓ il contenuto principale della pagina.

Ricapitolando, la nostra struttura di men¨ con relativi sottomen¨ pu˛ essere schematizzata cosý:

Si noti, in particolare, che la voce "Deals & Gifts" Ŕ priva di sottomen¨.

Creazione del CSS

Ora che abbiamo la struttura HTML del nostro men¨, dobbiamo impostarne l'aspetto e il comportamento attraverso il CSS.

Innanzitutto impostiamo uno sfondo grigio scuro per la pagina e scegliamo un carattere sans-serif verde e uno sfondo grigio chiaro per la barra di navigazione:

html { background-color: rgb(60,40,60); } nav { background-color: #DDD; color: green; font-family: sans-serif; }

Quindi impostiamo la dimensione della barra di navigazione. Assegnamole una larghezza relativa espressa in em (cioŔ nell'unitÓ di misura relativa alla dimensione del testo), in modo tale che, anche se l'utente del nostro sito ridimensiona i caratteri, le voci di men¨ saranno sempre visibili per intero:

html { background-color: rgb(60,40,60); } nav { background-color: #DDD; color: green; font-family: sans-serif; width: 18em; }

Diamo un'occhiata a cosa abbiamo ottenuto finora:

Men¨ laterale formato da voci principali e sottomen¨ con <ul> e <li> visualizzati con i punti elenco di default

La barra laterale che contiene il men¨ di navigazione dovrebbe estendersi fino al limite inferiore della pagina, indipendentemente dalla lunghezza del men¨. Dobbiamo allora assegnarle un'altezza pari al 100% del suo contenitore:

html { background-color: rgb(60,40,60); } nav { background-color: #DDD; color: green; font-family: sans-serif; width: 18em; height: 100%; }

Vediamo se abbiamo ottenuto il nostro scopo:

La nostra pagina dopo aver impostato height: 100% per l'elemento <nav>: ancora non abbiamo ottenuto il comportamento desiderato

MacchÚ! La situazione non Ŕ cambiata di una virgola, se non per la comparsa del bordo giallo, che abbiamo aggiunto all'elemento <html> per capire il motivo per cui la barra di navigazione non ha assunto le dimensioni desiderate.

Il bordo giallo ci permette di comprendere che l'elemento <html> non ha "di default" l'altezza del viewport. A meno che non la impostiamo noi come tale:

html { background-color: rgb(60,40,60); height: 100%; } nav { background-color: #DDD; color: green; font-family: sans-serif; width: 18em; height: 100%; }

La figura seguente (in particolare il bordo giallo) mostra che, pur avendo ottenuto l'altezza desiderata per l'elemento <html>, non abbiamo ottenuto l'"estensione" dell'altezza della barra di navigazione.

La nostra pagina dopo aver impostato height: 100% per l'elemento <nav>: ancora non abbiamo ottenuto il comportamento desiderato

La ragione Ŕ semplice: il genitore del nostro elemento <nav> non Ŕ l'elemento <html>, bensý l'elemento <body>. Quindi la barra assume il 100% dell'altezza del <body>, che per˛ al momento, non avendo un valore assegnato per la proprietÓ height, regola la propria altezza in base al contenuto della pagina.

Provvediamo allora ad assegnare esplicitamente al <body> un'altezza pari al 100% dell'elemento <html>:

html { background-color: rgb(60,40,60); height: 100%; } body { height: 100%; } nav { background-color: #DDD; color: green; font-family: sans-serif; width: 18em; height: 100%; }

Ed ecco finalmente il risultato desiderato:

La nostra pagina dopo aver impostato height: 100% per l'elemento <body>: finalmente abbiamo ottenuto il comportamento desiderato

(Dal momento che non ci serve pi¨, ho anche eliminato il bordo giallo.)

Ci sono dei margini indesiderati attorno alla barra. Facciamo cosý: eliminiamo tutti i margini e i padding che il browser assegna di default, in modo che poi potremo impostare solo quelli che desideriamo, avendo il completo controllo del nostro layout. L'applicazione di margin:0 e padding:0 a tutti gli elementi della pagina (indicati dal selettore *) si chiama "normalizzazione".

Contemporaneamente, eliminiamo i punti elenco, che non si addicono a delle voci di men¨, attraverso l'impostazione list-style:none per entrambi gli elementi <ul>, sia quello che contiene il men¨ principale che quello relativo ai sottomen¨.

* { margin: 0; padding: 0; } html { background-color: rgb(60,40,60); height: 100%; } body { height: 100%; } nav { background-color: #DDD; color: green; font-family: sans-serif; width: 18em; height: 100%; } nav>ul { list-style: none; } nav>ul>li>ul { list-style: none; }

Ora che abbiamo tolto tutti i margini e le decorazioni, ci troviamo con un men¨ tutto da formattare:

Men¨ senza decorazioni: nessun punto elenco, nessun padding, nessun margine

Iniziamo aggiungendo un po' di padding ai sottomen¨:

nav>ul { list-style: none; } nav>ul>li>ul { list-style: none; padding-left: 1em; }

Ecco un particolare di quanto ottenuto:

Rispetto all'immagine precedente, ora ai sottomen¨ Ŕ stato assegnato un rientro attraverso la proprietÓ padding

Proseguiamo assegnando alle voci dei sottomen¨ un carattere leggermente pi¨ piccolo rispetto alle voci del men¨ principale, e inserendo un po' di spazio tra le voci dei sottomen¨. Inserisci questo codice in coda al CSS scritto finora:

nav>ul>li>ul>li { padding-top: 0.5em; font-size: 0.9em; }

Anche tra un sottomen¨ e il successivo c'Ŕ bisogno di un po' pi¨ di separazione. Assegniamo un padding-top a ciascuna voce di sottomen¨:

nav>ul { list-style: none; } nav>ul>li { padding-top: 0.7em; } nav>ul>li>ul { list-style: none; padding-left: 1em; }

La figura seguente mostra l'effetto delle ultime proprietÓ impostate:

Il nostro men¨ dopo la regolazione di alcuni padding e il rimpicciolimento delle voci del men¨ secondario

Il men¨ Ŕ troppo "attaccato" al margine sinistro del viewport: diamogli un po' di padding. Poi cambiamo l'aspetto del puntatore del mouse al passaggio sopra il men¨.

nav>ul { list-style: none; padding-left: 0.5em; cursor: pointer; }

Possiamo anche regolare la dimensione della barra laterale, che, dopo la riduzione dei padding e della dimensione del font dei sottomen¨ rispetto a quelli di default, ora ha bisogno di una larghezza inferiore:

nav { background-color: #DDD; color: green; font-family: sans-serif; width: 14em; height: 100%; }

Ecco l'effetto dell'applicazione di queste ultime proprietÓ:

Il nostro men¨ dopo la regolazione del padding e della larghezza dell'intero men¨

Ora nascondiamo i sottomen¨: ognuno di essi dovrÓ apparire solo al passaggio del mouse sulla corrispondente voce del men¨ principale. Per farlo, dobbiamo:

  1. ridurre l'altezza di ciascun elemento <li> del men¨ principale, in modo che contenga solo la voce del men¨ principale, lasciando fuori il sottomen¨;
  2. nascondere il sottomen¨ che Ŕ "fuoriuscito" in seguito alla riduzione dell'altezza.

Si tratterÓ quindi di impostare le proprietÓ height e overflow degli elementi nav>ul>li:

nav>ul>li { padding-top: 0.7em; height: 1em; overflow: hidden; }

I sottomen¨ sono "scomparsi", come desiderato:

Il nostro men¨ con i sottomen¨ nascosti (grazie all'impostazione delle proprietÓ height e overflow

Al passaggio del mouse sulla voce di men¨, questa deve cambiare di altezza lasciando apparire il relativo sottomen¨. Quale altezza impostare, se i sottomen¨ hanno tutti altezze diverse, dipendenti dal numero di voci da cui sono composti? Ovvio: height:auto, in modo che il browser regoli l'altezza scegliendo il valore pi¨ adeguato:

nav>ul>li { padding-top: 0.7em; height: 1em; overflow: hidden; } nav>ul>li:hover { height: auto; }

La figura seguente dimostra che tutto funziona:

I sottomen¨ si aprono al passaggio del puntatore del mouse

C'Ŕ solo un ultimo dettaglio da sistemare: l'apertura dei sottomen¨ Ŕ troppo brusca. Per fare in modo che essa avvenga pi¨ dolcemente si pu˛ utilizzare una transizione.

Una transizione non Ŕ altro che il passaggio graduale di una proprietÓ da un valore di partenza ad uno di arrivo. La proprietÓ "soggetta" alla transizione Ŕ indicata assegnando un valore alla proprietÓ transition-property. La transizione Ŕ regolabile attraverso alcuni parametri come transition-duration e transition-timing-function: la prima determina la durata della transizione, la seconda la funzione che regola la "distribuzione" della transizione sulla sua durata (velocitÓ costante dall'inizio alla fine; pi¨ veloce all'inizio, meno alla fine; pi¨ lenta all'inizio, pi¨ veloce alla fine; ecc.). Dopo qualche prova, ho individuato i valori pi¨ soddisfacenti per queste proprietÓ:

nav>ul>li { padding-top: 0.7em; height: 1em; overflow: hidden; transition-property: height; transition-duration: 1s; transition-timing-function: linear; }

Le tre proprietÓ che abbiamo impostato per definire la transizione, possono essere impostate in un'unica riga di codice attraverso la sola proprietÓ transition:

nav>ul>li { padding-top: 0.7em; height: 1em; overflow: hidden; transition: height 1s linear; }

Sfortunatamente, il codice precedente non funziona: la transizione non avviene. PerchÚ?

PerchÚ non Ŕ possibile effettuare una transizione che coinvolga, come valore di partenza o di arrivo, il valore auto. Ma non possiamo sostituire auto con un valore ben determinato. Come ne usciamo?

Semplice: invece di utilizzare la proprietÓ height, utilizziamo max-height e applichiamo la transizione ad essa, assegnandole un valore finale maggiore del sottomen¨ pi¨ "lungo" tra quelli che abbiamo (o che ipotizziamo di avere in futuro):

nav>ul>li { padding-top: 0.7em; max-height: 1em; overflow: hidden; transition: max-height 1s linear; } nav>ul>li:hover { max-height: 15em; }

Ora il men¨ funziona come desideravamo.

A questo punto non ci resta altro da fare che associare dei collegamenti ipertestuali a ciascuna voce dei sottomen¨ o alle voci del men¨ principale che non abbiano sottomen¨ (come ad esempio, nel nostro caso, la voce Deals & Gifts) e che quindi devono aprire direttamente il link.

A mo' di esempio, associeremo ad ogni voce un link alla pagina di ricerca di Google relativa alla voce stessa. Riportiamo il codice HTML della terza e della quarta voce di men¨: la terza Ŕ la pi¨ breve, e quindi ci fa risparmiare spazio; la quarta Ŕ l'unica che non ha sottomen¨, quindi ha una struttura leggermente diversa. La struttura delle altre voci Ŕ facilmente deducibile da queste due.

<li>Home & Garden <ul> <li><a href="https://www.google.it/search?q=home+crafts">Crafts</a></li> <li><a href="https://www.google.it/search?q=home+dÚcor">Home DÚcor</a></li> <li><a href="https://www.google.it/search?q=pet+supplies">Pet Supplies</a></li> </ul> </li> <li><a href="https://www.google.it/search?q=deals+gifts">Deals & Gifts</a> </li>

Come forse avevi giÓ immaginato, gli elementi <a> sono contenuti all'interno degli elementi <li>.

Se provi a visualizzare il men¨ dopo queste modifiche, noterai che le voci a cui hai associato il link hanno i colori e la sottolineatura di default dei collegamenti ipertestuali.

Per modificare queste impostazioni puoi aggiungere questo codice in coda al file CSS:

nav a { color: green; text-decoration: none; } nav a:visited { color: purple; }

Vale forse la pena ricordare il significato dei selettori utilizzati. Il selettore nav a identifica tutti gli elementi <a> contenuti all'interno di un elemento <nav>, non importa quanti livelli al di sotto di esso; a differenza, ad esempio, del selettore nav>a (non presente nel nostro codice), che avrebbe indicato solo gli elementi <a> figli (ossia discendenti diretti) di un elemento <nav>.

Il selettore nav a:visited, poi, identifica tutti gli elementi <a> contenuti all'interno di un elemento <nav> il cui collegamento sia stato giÓ visitato.

Ecco finalmente il nostro men¨ completo e finito:

Il nostro men¨ completo e finito