Developpez.com - Développement Web
X

Choisissez d'abord la catégorieensuite la rubrique :


Des menus déroulants grâce aux CSS

01/06/2004

Par Marc Hertzog (Site internet)

Objectif : réaliser un menu déroulant XHTML + CSS (sans javascript) avec fonds transparents.
Inconvénients : seuls quelques navigateurs récents (Mozilla/Firebird, Safari) seront capables de rendre ce menu correctement.
En contre-partie, comme IE Windows n'affichera pas les sous-menu, il y a possibilité d'utiliser des PNG avec transparence alpha.


La structure
Le style
Le Menu Magique
Le résultat


La structure

La première étape consiste à définir la structure de notre menu. Dans mon cas, je vais faire simple pour ce premier essai et faire un seul sous niveau. On aura donc le premier niveau visible, et un sous-niveau déroulant.
Je vais commencer par le menu principal avec une liste non-ordonnée qui commence par un élément <ul>. Chaque item de cette liste de premier niveau démarre par un élément <li> et contient des liens <a> vers les rubriques de tout premier niveau. Ces liens sont importants pour les navigateurs qui n'afficheront pas les menus-déroulants :

<ul> <li><a href="#">Partie 1</a></li> <li><a href="#">Partie 2 </a></li> <li><a href="#">Partie 3</a></li> <li><a href="#">Partie 4</a></li> </ul>

J'enchaîne en imbriquant des sous-niveaux. Dans la structure du code, ça va se traduire par une autre liste dans chaque item <li> de ma première liste :

<ul> <li> <a href="#">Partie 1</a> <ul> <li><a href="#">castor</a></li> <li><a href="#">aligator</a></li> <li><a href="#">musclor</a></li> </ul> </li> <li> <a href="#">Partie 2</a> <ul> <li><a href="#">whisky</a></li> <li><a href="#">vodka</a></li> <li><a href="#">gin</a></li> <li><a href="#">vin</a></li> <li><a href="#">champagne</a></li> </ul> </li> <li> <a href="#">Partie 3</a> <ul> <li><a href="#">pommes</a></li> <li><a href="#">poires</a></li> <li><a href="#">ananas</a></li> <li><a href="#">pamplemousse</a></li> <li><a href="#">banane</a></li> <li><a href="#">raisins</a></li> <li><a href="#">framboises</a></li> <li><a href="#">fraises</a></li> <li><a href="#">mirabelles</a></li> <li><a href="#">groseilles</a></li> </ul> </li> <li> <a href="#">Partie 4</a> <ul> <li><a href="#">tomates</a></li> <li><a href="#">haricots</a></li> <li><a href="#">carrottes</a></li> <li><a href="#">choux</a></li> <li><a href="#">concombres</a></li> <li><a href="#">courgettes</a></li> <li><a href="#">endives</a></li> <li><a href="#">navets</a></li> <li><a href="#">epinards</a></li> <li><a href="#">avocat</a></li> </ul> </li> </ul>

Avant de commencer à mettre du style, je vais donner des identifiants et des classes à mes éléments pour pouvoir y accéder sans ambiguïté via ma feuille de style CSS. Comme mon menu de navigation va être unique sur ma page, je peux me permettre de donner un identifiant id unique à l'élément <ul> de premier niveau. Par contre je vais styler tous mes sous menu de la même façon. Je vais donc devoir leur affecter une même classe, pas d'id car ce dernier doit-être unique. Si je ne différencie pas mes sous-niveaux avec des classes, ils vont hériter de certaines propriétés de leur(s) élément(s) parent(s) dans l'arbre du document. Au final, on a le code suivant :

<ul id="menuDeroulant"> <li> <a href="#">Partie 1</a> <ul class="sousMenu"> <li><a href="#">castor</a></li> <li><a href="#">aligator</a></li> <li><a href="#">musclor</a></li> </ul> </li> <li> <a href="#">Partie 2</a> <ul class="sousMenu"> <li><a href="#">whisky</a></li> <li><a href="#">vodka</a></li> <li><a href="#">gin</a></li> <li><a href="#">vin</a></li> <li><a href="#">champagne</a></li> </ul> </li> [...] </ul>

Le style

A partir de maintenant, tout se passe dans la feuille de style.
Pour cet exemple je vais définir la taille des caractères directement sur body histoire de ne pas alourdir le reste du code. Je vais définir la taille de mon texte en pixels (oui, je sais qu'il y a mieux comme unité). Pour bien voir la future transparence de mes sous-menus, je vais mettre une image de fond sur la page. Finalement, pour que ma page colle aux bords de la fenêtre du navigateur, je donne 0 comme valeur aux propriétés margin et padding de <body> :

body { font: 11px verdana, sans-serif; background: #AFA99B url("fond.jpg") top left no-repeat; margin: 0; padding: 0; }

Ensuite, on s'occupe du style des listes.
Il faut que ma liste principale s'affiche de façon horizontale et ne présente pas de puces comme elle le fait par défaut, et que ses items <li> soient alignées horizontalement. Il y a deux méthodes répandues pour faire ça : utiliser display: inline ou faire flotter les éléments <li>. Chaque méthode a ses avantages et ses inconvénients. J'ai choisi de faire flotter les éléments. Pour cet exemple, comme l'image de fond que j'ai collé sur <body> fait 644px, je donne une largeur de 644px à ma liste. Important également, les bords, les marges et le remplissage à 0 pour homogénéiser le rendu en fonction des différents navigateurs :

#menuDeroulant { width: 644px; list-style-type: none; margin: 0; padding: 0; border: 0; } #menuDeroulant li { float: left; margin: 0; padding: 0; border: 0; }

Occupons-nous de nos sous-menus. Commençons par empêcher l'affichage des puces en utilisant list-style-type: none; sur les éléments <ul> de nos sous-menus. Comme nous avons fait flotter à gauche les éléments <li> parents de nos sous-menus, ces derniers vont hériter de cette propriété. Il faut que nous empêchions les éléments <li> de notre sous-menu de flotter, pour cela on utilise float: none :

#menuDeroulant .sousMenu { list-style-type: none; margin: 0; padding: 0; border: 0; } #menuDeroulant .sousMenu li { float: none; margin: 0; padding: 0; border: 0; }

Nous sommes maintenant confrontés à un problème si nous voulons que notre menu ait une apparence correcte dans IE5 Mac.
Dans la majorité des navigateurs récents, lorsqu'un élément flottant contient un autre élément, la largeur de l'élément flottant conteneur est réduite à la largeur de son contenu.
Dans IE5 Mac, il y a un bug qui fait que lorsqu'un élément de type block et de largeur automatique (width: auto) est contenu dans un élément flottant, IE5 Mac fait prendre à cet élément et à son conteneur flottant toute la largeur disponible dans la fenêtre du navigateur.
Dans notre cas, les éléments conteneur flottants sont les éléments <li> de notre liste de premier niveau. Les éléments contenus de type block sont les éléments <li> de nos listes de second niveau. Par défaut leur largeur est définie en automatique si nous ne la spécifions pas.
La seule solution que j'ai trouvée à l'heure actuelle c'est de donner une largeur explicite aux éléments <li> de notre menu de premier niveau qui sera héritée par nos menus de second niveaux.

#menuDeroulant li { float: left; width: 150px; margin: 0; padding: 0; border: 0; }

Maintenant, je vais m'occuper de l'apparence du menu déroulant en donnant du style aux liens contenus dans nos listes. Je vais faire passer les éléments <a> de leur type inline par défaut à un type block via display: block; et styler les différents états des liens.
Pour donner un fond transparent, il faut créer dans un logiciel de création d'image un rectangle de couleur uni avec un niveau de transparence alpha à 60% par exemple et l'enregistrer au format PNG. Puis je le place en tant qu'image de fond des liens de nos sous-menus :

#menuDeroulant li a:link, #menuDeroulant li a:visited { display: block; height: auto; color: #FFF; background: #3B4E77; margin: 0; padding: 4px 8px; border-right: 1px solid #fff; text-decoration: none; } #menuDeroulant li a:hover { background-color: #F2462E; } #menuDeroulant li a:active { background-color: #5F879D; } #menuDeroulant .sousMenu li a:link, #menuDeroulant .sousMenu li a:visited { display: block; color: #FFF; margin: 0; border: 0; text-decoration: none; background: transparent url("fondTR.png") repeat; } #menuDeroulant .sousMenu li a:hover { background-image: none; background-color: #F2462E; }

Pour plus de raffinement et dans l'esprit de la transparence, nous pouvons donner un bord supérieur et un bord droit transparents aux éléments <li> de nos sous-menus. Comme nous ajoutons 1px de bord droit, il ne faut pas oublier de redéfinir la taille de nos sous-menus en leur retranchant 1px, car la largeur totale d'un élément = width + margin + border + padding :

#menuDeroulant .sousMenu li { float: none; margin: 0; padding: 0; border: 0; width: 149px; border-top: 1px solid transparent; border-right: 1px solid transparent; }

Le Menu Magique

Nous allons maintenant profiter des avancées technologiques des navigateurs récents alternatifs.
Masquons nos sous-menus avec display: none :

#menuDeroulant .sousMenu { display: none; list-style-type: none; margin: 0; padding: 0; border: 0; }

Enfin, appliquons un état :hover à nos éléments <li> de notre liste de premier niveau :

#menuDeroulant li:hover > .sousMenu { display: block; }

Le résultat

Voir le résultat en ligne (nouvelle fenêtre).


Note de la rédaction de developpez.com

Cet article a été publié à l'origine sur le site de l'auteur et est encore visible à l'adresse suivante : http://marcarea.com/tuto/menu01.php


Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.
Responsable bénévole de la rubrique Développement Web : Xavier Lecomte -