Présentation

Image non disponible
Voir une démo en ligne

Si vous êtes pressé, vous pouvez déjà voir un exemple en ligne.

Sinon voici un aperçu du menu déroulant animé que nous allons créer en CSS3 :

Image non disponible

Vous vous souvenez de mon précédent menu déroulant CSS3 ? Ce menu vous a beaucoup plu et est à l'heure actuelle l'article le plus populaire de mon site.

Cet article aurait peut-être dû s'appeler « Un menu déroulant en CSS3 revisité ». Je dis cela car je vais vous apprendre à animer le menu déroulant de l'exemple de l'article précédent.

Le HTML

La structure HTML n'a pas du tout changé, simple et minimale. En voici un extrait :

 
Sélectionnez

<ul id="menu">
        <li><a href="#">Home</a></li>
        <li>
                <a href="#">Categories</a>
                <ul>
                        <li><a href="#">CSS</a></li>
                        <li><a href="#">Graphic design</a></li>
                        <li><a href="#">Development tools</a></li>
                        <li><a href="#">Web design</a></li>
                </ul>
        </li>
        <li><a href="#">Work</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
</ul>

Le CSS

J'ai en revanche un peu remanié les styles pour permettre d'animer ce magnifique menu déroulant CSS3. Voici donc les différentes portions de code commentées.

Mini reset

D'abord, nous réinitialisons certains styles par défaut des balises <ul>.

 
Sélectionnez

#menu, #menu ul {
        margin: 0;
        padding: 0;
        list-style: none;
}

Niveau principal

L'élément #menu correspond à la balise <ul> contenant le menu. Nous lui appliquons un dégradé, des ombres et des coins arrondis pour lui donner l'aspect suivant :

Image non disponible
 
Sélectionnez

#menu {
        width: 960px;
        margin: 60px auto;
        border: 1px solid #222;
        background-color: #111;
        background-image: -moz-linear-gradient(#444, #111);
        background-image: -webkit-gradient(linear, left top, left bottom, from(#444), to(#111));
        background-image: -webkit-linear-gradient(#444, #111);
        background-image: -o-linear-gradient(#444, #111);
        background-image: -ms-linear-gradient(#444, #111);
        background-image: linear-gradient(#444, #111);
        -moz-border-radius: 6px;
        -webkit-border-radius: 6px;
        border-radius: 6px;
        -moz-box-shadow: 0 1px 1px #777;
        -webkit-box-shadow: 0 1px 1px #777;
        box-shadow: 0 1px 1px #777;
}

Annuler les flottements

J'ai repris ici la méthode de Nicolas Gallagher pour annuler le flottement :

 
Sélectionnez

#menu:before,
#menu:after {
        content: "";
        display: table;
}

#menu:after {
        clear: both;
}

#menu {
        zoom:1;
}

Éléments de liste

Image non disponible

Notez la présence du sélecteur #menu li:hover > a. C'est probablement l'astuce la plus importante pour réaliser ce menu déroulant CSS3 !

Son fonctionnement est de sélectionner une balise <a>, qui est enfant d'une balise <li>, qui elle-même est un descendant de #menu. Voir une description détaillée.

 
Sélectionnez

#menu li {
        float: left;
        border-right: 1px solid #222;
        -moz-box-shadow: 1px 0 0 #444;
        -webkit-box-shadow: 1px 0 0 #444;
        box-shadow: 1px 0 0 #444;
        position: relative;
}

#menu a {
        float: left;
        padding: 12px 30px;
        color: #999;
        text-transform: uppercase;
        font: bold 12px Arial, Helvetica;
        text-decoration: none;
        text-shadow: 0 1px 0 #000;
}

#menu li:hover > a {
        color: #fafafa;
}

*html #menu li a:hover { /* IE6 only */
        color: #fafafa;
}

Sous-menus

Avec les transitions CSS3, nous pouvons animer les changements de valeurs des propriétés comme margin ou opacity. C'est plutôt sympa et j'ai utilisé cette méthode pour animer les sous-menus CSS3. Si vous me demandez mon avis, je dirais que le résultat est excellent :

Image non disponible
 
Sélectionnez

#menu ul {
        margin: 20px 0 0 0;
        _margin: 0; /*IE6 only*/
        opacity: 0;
        visibility: hidden;
        position: absolute;
        top: 38px;
        left: 0;
        z-index: 9999;
        background: #444;
        background: -moz-linear-gradient(#444, #111);
        background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #111),color-stop(1, #444));
        background: -webkit-linear-gradient(#444, #111);
        background: -o-linear-gradient(#444, #111);
        background: -ms-linear-gradient(#444, #111);
        background: linear-gradient(#444, #111);
        -moz-box-shadow: 0 -1px rgba(255,255,255,.3);
        -webkit-box-shadow: 0 -1px 0 rgba(255,255,255,.3);
        box-shadow: 0 -1px 0 rgba(255,255,255,.3);
        -moz-border-radius: 3px;
        -webkit-border-radius: 3px;
        border-radius: 3px;
        -webkit-transition: all .2s ease-in-out;
        -moz-transition: all .2s ease-in-out;
        -ms-transition: all .2s ease-in-out;
        -o-transition: all .2s ease-in-out;
        transition: all .2s ease-in-out;
}

#menu li:hover > ul {
        opacity: 1;
        visibility: visible;
        margin: 0;
}

#menu ul ul {
        top: 0;
        left: 150px;
        margin: 0 0 0 20px;
        _margin: 0; /*IE6 only*/
        -moz-box-shadow: -1px 0 0 rgba(255,255,255,.3);
        -webkit-box-shadow: -1px 0 0 rgba(255,255,255,.3);
        box-shadow: -1px 0 0 rgba(255,255,255,.3);
}

#menu ul li {
        float: none;
        display: block;
        border: 0;
        _line-height: 0; /*IE6 only*/
        -moz-box-shadow: 0 1px 0 #111, 0 2px 0 #666;
        -webkit-box-shadow: 0 1px 0 #111, 0 2px 0 #666;
        box-shadow: 0 1px 0 #111, 0 2px 0 #666;
}

#menu ul li:last-child {
        -moz-box-shadow: none;
        -webkit-box-shadow: none;
        box-shadow: none;
}

#menu ul a {
        padding: 10px;
        width: 130px;
        _height: 10px; /*IE6 only*/
        display: block;
        white-space: nowrap;
        float: none;
        text-transform: none;
}

#menu ul a:hover {
        background-color: #0186ba;
        background-image: -moz-linear-gradient(#04acec,  #0186ba);
        background-image: -webkit-gradient(linear, left top, left bottom, from(#04acec), to(#0186ba));
        background-image: -webkit-linear-gradient(#04acec, #0186ba);
        background-image: -o-linear-gradient(#04acec, #0186ba);
        background-image: -ms-linear-gradient(#04acec, #0186ba);
        background-image: linear-gradient(#04acec, #0186ba);

Style des premiers et derniers éléments de liste

Image non disponible
 
Sélectionnez

#menu ul li:first-child > a {
        -moz-border-radius: 3px 3px 0 0;
        -webkit-border-radius: 3px 3px 0 0;
        border-radius: 3px 3px 0 0;
}

#menu ul li:first-child > a:after {
        content: '';
        position: absolute;
        left: 40px;
        top: -6px;
        border-left: 6px solid transparent;
        border-right: 6px solid transparent;
        border-bottom: 6px solid #444;
}

#menu ul ul li:first-child a:after {
        left: -6px;
        top: 50%;
        margin-top: -6px;
        border-left: 0;
        border-bottom: 6px solid transparent;
        border-top: 6px solid transparent;
        border-right: 6px solid #3b3b3b;
}

#menu ul li:first-child a:hover:after {
        border-bottom-color: #04acec;
}

#menu ul ul li:first-child a:hover:after {
        border-right-color: #0299d3;
        border-bottom-color: transparent;
}

#menu ul li:last-child > a {
        -moz-border-radius: 0 0 3px 3px;
        -webkit-border-radius: 0 0 3px 3px;
        border-radius: 0 0 3px 3px;
}

Le jQuery

Vous y êtes habitués : IE6 réclame quelques attentions supplémentaires :

 
Sélectionnez

$(function() {
  if ($.browser.msie && $.browser.version.substr(0,1)<7)
  {
        $('li').has('ul').mouseover(function(){
                $(this).children('ul').css('visibility','visible');
                }).mouseout(function(){
                $(this).children('ul').css('visibility','hidden');
                })
  }
});

Puisque la pseudoclasse :hover ne fonctionne pas sur des éléments autres que des liens, nous devons ajouter ce petit code jQuery. Le code est suffisamment explicite selon moi.

Voir un exemple en ligne.

Conclusion et remerciements

C'est terminé. Si cet article vous a plu, n'hésitez pas à le commenter et à proposer vos idées d'améliorations. (NDT Y compris sur le site de l'article original.)

Cet article a été publié avec l'aimable autorisation de Catalin Rosu. L'article original peut être lu sur le site de Red Team Design : CSS3 animated dropdown menu.

Nous tenons aussi à remercier bifconsult pour sa relecture attentive de cet article.