[CSS]Effet sur menu multi-niveaux

NoSmoking

Le menu

La structure de base

La structure est une structure classique sur base de l'utilisation de listes <ul> même si des listes <ol> pourraient également convenir, un menu étant quand même, à priori, quelque chose d'ordonné.

<ul class="menu">
  <li>Menu #1
    <ul>
      <li><a href="#">Sous Menu 1</a></li>
      <li>Sous Menu 2
        <ul>
          <li><a href="#">Sous Menu 2.1</a></li>
          <li><a href="#">Sous Menu 2.2</a></li>
          <li>Sous Menu 2.3
            <ul>
              <li><a href="#">Sous Menu 2.3.1</a></li>
              <li><a href="#">Sous Menu 2.3.2</a></li>
            </ul>
          </li>
          <li><a href="#">Sous Menu 2.4</a></li>
        </ul>
      </li>
      <li><a href="#">Sous Menu 3</a></li>
      <li><a href="#">Sous Menu 4</a></li>
    </ul>
  </li>
</ul>

Le principe

L'effet donne l'impression que le menu s'ouvre du haut à gauche vers le bas à droite en grossissant.

Pour réaliser cet effet nous allons utiliser la propriété CSS3 transform et notamment sa valeur/fonction scale(x) en passant de la valeur x=0 à x=1.

Il est à noter que l'origine par défaut pour la fonction scale(x), et d'autres, est le centre de l'élément. Il nous faut donc déplacer cette origine pour réaliser notre effet, pour cela nous disposons de la propriété transform-origin qui permet justement de modifier l'origine du repère pour les opérations de transformation d'un élément.

Nous allons donc modifier la propriété transform-origin permet de modifier l'origine du repère pour les opérations de transformation d'un élément.

Nous allons donc modifier la propriété transform-origin en lui affectant les valeurs left top ce qui placera l'origine de l'effet de grandissement en haut et à gauche.

Nous allons donc appliquer une transform-origin: left top, équivalente à transform-origin: 0 0 ce qui placera l'origine de l'effet de grandissement en haut et à gauche.

Lors de l'application d'un transform:scale(x) sur un élément, la place occupée par celui ci dans le flux reste inchangée, ses frères ne sont pas déplacés.

Pour finir, nous allons utiliser la propriété CSS3 transition pour passer des valeurs de départ aux valeurs d'arrivée d'une « façon fluide » et ce au déclenchement d'un événement sur un élément du menu, en l'occurrence la pseudo-classe :hover.

Pour résumer le CSS de l'effet :

.menu li ul {
  opacity:0;
  transform: scale(0);
  transform-origin: left top;
  transition:all 0.5s ease;
  z-index:0;
}
.menu li:hover > ul{
  opacity:1;
  transform: scale(1);
  z-index:100;          /* important */
}

Pour être honnête

Ce menu n'est quand même pas un modèle du genre pour des raisons de clarté et d'accessibilité, pensez que vous êtes sur une page Web et non dans un logiciel de bureau. Il est conseillé de ne pas dépasser plus d'un niveau.

Ce menu n'est pas adapté pour un support tactile.

Ce menu fonctionne sous IE9 et moins « à plat », sans aucun effet de transition, et ceci grâce à l'ajout d'un commentaire conditionnel modifiant l'aspect des éléments.

<!-- à partir de IE10 les commentaires conditionnels ne sont plus pris en compte -->
<!--[if IE]>
<style>
/* ayons pitié des "old browser" */
.menu li ul {
  display:none;
}
.menu li:hover > ul{
  display:block;
}
</style>
<![endif]-->

Ressources