loading

JohnnyBEHAGUE

Créer votre propre menu Burger !

Aujourd’hui nous allons voir comment faire un menu burger responsive en HTML et pur CSS, sans aucun ajout de Javascript !

Tout est parti d’un constat simple : lors de mon mentorat OpenClassrooms, j’aiguillais mes étudiants sur la réalisation de leur projet HTML, et à un moment ils étaient amenés à gérer la partie responsive du menu. Bien qu’il y ait des solutions relativement simples pouvant être mises en place,j’ai préféré les mettre au défi de faire un menu burger, ce fameux menu que l’on voit très souvent lors de navigation sur mobile. Mais en me prêtant au jeu, je me suis aperçu que ce n’est pas forcément évident : l’implémentation peut être assez simple, mais cela demande beaucoup de rigueur et de méthode, et n’est pas forcément accessible pour un néophyte… Voyons cela par étape tous ensemble !

Etape 1 : Création du menu classique

Nous allons tout d’abord créer notre menu classique. Pour les besoins du tutoriel, je vais faire un code relativement simple, sans balises superflues (nav, etc) : bien sûr, adaptez ce code à votre situation !

<!DOCTYPE html>
<html lang="fr">
    <head>
        <meta charset="UTF-8" />
        <title>Burger menu</title>
        <meta name="description" content="Burger menu responsive" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <ul>
            <li><a href="#">Menu 1</a></li>
            <li><a href="#">Menu 2</a></li>
            <li><a href="#">Menu 3</a></li>
            <li><a href="#">Menu 4</a></li>
        </ul>
    </body>
</html>
ul {
    display: flex;
    flex-direction: row;
}
li {
    list-style-type: none;
    padding: 10px;
}
a {
    text-decoration: none;
    color: #000000;
}

En lançant notre page, nous avons notre menu horizontal: parfait, c’est ce qu’on doit obtenir sur une résolution « classique »!

Menu horizontal

Nous allons garder notre code, et essayer d’avoir maintenant le comportement cible sur mobile : comme ça, une fois que c’est fait, on a juste a implémenté notre code existant dans une media query, et le tour est joué, cela évite de perdre du temps à manipuler l’inspecteur de développement.

Etape 2 : Ajout de l’icône Burger

Pour l’icône Burger, vous avez sans doute deviner, nous allons utiliser une icône FontAwesome.

Pour cela, on va ajouter le CSS correspondant :

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

Comme nous allons avoir de plus en plus de code, nous allons englober cette partie dans une div, que je vais identifier comme « burger », et mettre mon icône juste avant le menu.

        <div id="burger">
            <i class="fa fa-bars fa-2x" aria-hidden="true"></i>
            <ul>
                <li><a href="#">Menu 1</a></li>
                <li><a href="#">Menu 2</a></li>
                <li><a href="#">Menu 3</a></li>
                <li><a href="#">Menu 4</a></li>
            </ul>
        </div>

Si on regarde l’aperçu, voici ce qu’on obtient :

Menu horizontal avec burger

Sauf que lorsque l’on aura notre burger affiché, l’idéal serait d’afficher le menu verticalement… ce qui sera rapide avec la flexbox !

ul {
    display: flex;
    flex-direction: column; /* => A utiliser quand le burger est affiché */
    /* flex-direction: row; => A utiliser quand le burger n'est pas affiché */
}
Menu vertical avec burger

Cela commence à ressembler à quelque chose non ?

Etape 3 : Affichage du menu via le burger

Maintenant, nous allons conditionner l’affichage du menu selon le burger. Forcément, le menu ne sera pas tout le temps visible, sinon le bouton burger serait inutile. Cependant, notre balise <i> ne peut pas gérer un état checked qui peut nous aider niveau CSS… Comment peut-on faire dans ce cas-là ?

Dans un premier temps, nous allons conditionner le menu via une simple checkbox.

<div id="burger">
  <i class="fa fa-bars fa-2x" aria-hidden="true"></i>
  <input type="checkbox" id="burger_checkbox"/>
  <ul id="menu">
     <li><a href="#">Menu 1</a></li>
     <li><a href="#">Menu 2</a></li>
     <li><a href="#">Menu 3</a></li>
     <li><a href="#">Menu 4</a></li>
  </ul>
</div>
input[type="checkbox"]:not(:checked) + ul {
 display: none;
}
input[type="checkbox"]:checked + ul {
display: flex;
}

Avec ce bout de code là, on conditionne déjà l’affichage du menu via la checkbox, et on a fait le plus dur !

Maintenant, l’astuce est en fait de cacher l’icône checkbox, et de le remplacer  par une icône fontawesome : la démarche n’étant pas compliquée mais nécessitant de la méthode, j’ai créé un billet dédié que je vous invite à lire 🙂 .

Maintenant que mon icône est ajouté, il me reste une dernière chose à faire : implémenter la media query qui me dira quand afficher le burger.

Etape 4 : Ajout de la Media Query

Si vous vous souvenez, au début de notre code j’avais mis les valeurs flexbox-direction en commentaire : cela nous servira dès maintenant!

Faisons un rapide état des lieux de ce que nous voulons :

  • En grande résolution, un menu horizontal classique (sans burger)
  • En petite résolution, un burger qui pourra déplier un menu vertical

Nous allons définir une media query pour gérer la petite résolution et y ajouter au fur et à mesure nos modifications :

@media screen and (max-width: 640px) {
  
}

Un premier changement entre la petite et la grande résolution est l’orientation du menu (vertical / horizontal). En CSS cela donne :

ul {
    display: flex;
    flex-direction: row;
}

@media screen and (max-width: 640px) {
  ul {
    flex-direction: column;
  }
}

Maintenant, il suffira de rajouter l’intégralité des règles CSS liés à l’affichage du menu dans la media query :

@media screen and (max-width: 640px) { 
  /* Gestion de l'affichage du menu */
  input[type="checkbox"]:not(:checked) ~ ul {
    display: none;
  }
  input[type="checkbox"]:checked ~ ul {
    display: flex;
  }
  
  /* Gestion de la checkbox */
  input[type="checkbox"] + label:before {
    font-family: FontAwesome;
    font-size: 30px;
  }

  input[type="checkbox"] + label:before {
    content: "\f0c9";
  }

  input[type="checkbox"]:not(:checked) + label:before {
    content: "\f0c9";
  }

  input[type="checkbox"]:checked + label:before {
    content: "\f00d";
  }
}

Et c’est déjà fini, vous avez un beau menu burger responsive!

L’exemple est disponible sur CodePen.

A bientôt!

Leave a comment