CSS - Un menu déroulant

Ce billet  explique la réalisation d'un menu déroulant et illustre les définitions vues dans les billets CSS - la hiérarchie et CSS - le flux.
L'objectif est de réaliser la page affichée ci-dessous.

Les commentaires

Le corps de la page est constitué de 3 bloc div identifiés respectivement element1, menu et element2. Ces blocs sont stylisés respectivement #element1, #menu, #element2 avec un fond coloré background-color: qui permet de vérifier qu'ils s'empilent les uns sous les autres (même si, comme le bloc menu, il n'occupe pas toute la largeur de la page width:70%) conformément aux caractéristiques de type bloc.

Les listes <ul> sont imbriquées, elles forment les différentes profondeurs du menu et sont, chacune ,stylisée par une classe repérant la profondeur du menu.

  • r0 la racine du menu
  • r-1 le 1er niveau
  • r-2 le second niveau

Le style de ces listes doit contenir le paramètre list-style-type affecté de la valeur none pour faire disparaitre le point qui normalement  précède une liste. C'est effectué dans chacune des classes r0, r-1, r-2. C'est également dans ces classes que sont paramétrées les marges     margin:0; padding:0;
 

#menu .r0,
#menu .r-1,
#menu .r-2 {
    list-style-type:none;
    margin:0;
    padding:0;
}

Les listes <ul> autre que la racine (r-1 et r-2) du menu ne doivent pas être affichées lorsque la souris n'est pas sur zone. Les classes  r-1 et r-2 doivent contenir le paramètre display avec la valeur none.
Lorsqu'elles seront affichées, il ne faudra pas qu'elles poussent les autres blocs vers le bas d'où le paramètre position avec la valeur absolute qui fixe la place du bloc <ul> sous le dernier bloc positionné (ici l'élément <ul class="r0" >  la racine).

#menu .r-1,
#menu .r-2 {
    display : none;
    position : absolute;
}

Par défaut, les éléments <ul> et <li> qui constituent le menu (liste non ordonnée) s'empilent  car ils sont également de type bloc. Notre style va modifier ce comportement par défaut pour la liste racine. C'est le rôle du style .r0 > li { display:inline-block; }
La valeur inline-block est utilisée ici car inline (qui a la même fonction) ne permet pas d'agir sur les marges.
Le signe > est utilisé entre r0 et Li parce que seules les <li> filles de .r0 doivent s'afficher en ligne.

#menu .r0 > li {
    display:inline-block;

Le  style li a {} s'applique à tous les liens du menu. L'affichage display:block permet à cet élément inline par défaut d'avoir marge et dimension.

#menu  li a {
    display:block;
    width:250px;
    color:red;
    padding:5px;
    background-color:black;
    text-align:center;

Le style a:hover {} colorise les  liens  du menu au passage de la souris. Ce passage doit également déclencher le cas échant l'affichage du sous-menu. C'est le rôle du paramètre display affecté à la valeur block des styles li:hover .r-1{} et li:hover .r-1 li:hover .r-2{}. On en profite pour positionner le bloc.

 #menu  li:hover .r-1 {
    display:block;
    margin : -5px 20px;
}
 #menu  li:hover .r-1 li:hover .r-2 {
    display:block;
    margin : -5px 180px;
}

NB : aide à la lecture du style li:hover .r-1 li:hover .r-2

Ce style s'applique  sur les éléments B de classe r-2 à l'intérieur d'un élément <li> survolé par la souris, cet élément est lui-même à l'intérieur d'un élément B1 de classe r-1 qui est lui-même à l'intérieur d'un élément <li> survolé par la souris. La lecture s'effectue de la droite vers la gauche. Ce qui correspond à la portion de code HTML ci-dessous. A chaque fois que cette séquence se trouve dans le code, le style est appliqué. B1 peut être une balise HTML quelconque, mais dans notre fichier B1 est la balise <ul>, elle est la seule classée r-1. De même B peut être une balise HTML quelconque, mais dans notre fichier B est la balise <ul>, elle est la seule classée r-2

<li>
      ...
         <B classe="r-1">
                  ...
                      <li>
                            ....
                                <B classe="r-2">
                                                contenu concerné par le style
                                </B>
                           ....
                      </li>....
           </B>
      ....
</li>

Des onglets et des arrondis

Un toute petite modification augmente l'esthétique du menu (cf. onglet un style +++ ci-dessus)

Dans le version étudiée, le fond était stylisé dans li a {}. En supprimant ce paramètre et en ajoutant les styles ci-dessous, on obtient des arrondis pour les sous-menu de niveau 1 et 2.

#menu .r-2 {
    background-color:aqua;
    border: solid;
    border-width: thin;
    border-color: aqua;
  /* W3C standard--when adopted across the board */
    border-radius: 5px 15px 15px 5px;
}
#menu .r-1 {
    background-color:blue;
    border: solid;
    border-width: thin;
    border-color: blue;
  /* W3C standard--when adopted across the board */
    border-radius: 5px 15px 15px 5px;
}

Pour arrondir la racine du menu et l'afficher sous forme d'onglets, on modifiera le style .r0 > li {}. Les modifications apportées sont en gras.

#menu .r0 > li {
    display:inline-block;
    background-color:black;
    border: solid;
    border-width: thin;
    border-color: black;
    border-radius: 15px 15px 0px 0px;

}

Version Flexbox

Le 4 ème onglet ci-dessus permet de récupérer les styles CSS utilisant les propriétés flexbox.
Les modifications entre les versions CSS+++ et flexbox sont minimes (déplacement de certaines proprités vers le conteneur ( ie : de <li> vers <ul>)) et la disparition du bug d'affichage de display:inline-block (cette propriété n'étant plus utilisée : supprimée dans <li> mais compensée  par display:flex; flex-direction:row dans son conteneur <ul>))


Mots Clé