Aller au contenu principal
Partagez ce tutoriel :

Créer un menu hamburger en CSS

Dernière mise à jour : juin 2023

Introduction

Devenu incontournable sur les sites web et les applications, le menu dit "hamburger" ou "burger" peut se décliner de différentes manières. Symbolisé par un pictogramme ressemblant à un hamburger, celui-ci invite le visiteur à cliquer pour ouvrir un menu.

Très utile si votre menu contient de nombreuses rubriques, notamment sur mobile, il devient beaucoup moins pertinent si le menu n'affiche que trois ou quatre rubriques. Il faut donc se demander avant de le mettre en place s'il s'agit de la meilleure solution.

Minimaliste, sophistiqué, animé ou statique, nous allons voir dans ce tutoriel comment mettre en place ce type de pictogramme uniquement en CSS ainsi que le menu dans son ensemble.


Création de l'icône

On commence par placer un input de type checkbox (pour simuler un lien cliquable) auquel on attribue un identifiant unique et qu'on rattache à un label.



<input type="checkbox" id="votre_id">
<label for="votre_id"><span></span></label>


Nous allons dès lors styliser cette case à cocher. L'idée est de créer trois barres les unes en dessous des autres.

Les pseudo-éléments ::before et ::after.

Dans le code HTML plus haut, vous aurez remarqué la présence d'un élément span à l'intérieur du label. En effet, celui-ci va nous servir à créer les trois barres. Le label, quant à lui, aura pour fonction de conteneur. Comme nous allons utiliser le positionnement CSS pour placer les barres, le label sera en position relative.

L'élément span passe alors en position absolue venant prendre place au centre, tandis que les pseudo-éléments constituent la première ainsi que la dernière barre.

Ce qui nous donne ceci :


  
*,*::before,*:after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    


.menu_hamburger+label{


position: relative;
margin: 5rem auto;
display: flex;
justify-content: center;

	}
    

	
.menu_hamburger+label span{

position: absolute;	
top: 50%;
margin-top:-5px;
width:80px;
height:10px;
background-color:#6753ea;
border-radius: 20px;
	
	}

.menu_hamburger+label span::before {
	

position:absolute;
content:'';
width:inherit;
height:inherit;
background-color :inherit;
top: -20px;
border-radius: inherit;	
	}

.menu_hamburger+label span::after {
	

position:absolute;
content:'';
width:inherit;
height:inherit;
background-color: inherit;
bottom: -20px;
border-radius: inherit;	
	}		



On va ensuite utiliser les transformations CSS pour faire pivoter les barres. Tandis que la première et la deuxième vont fusionner pour ne faire qu'une seule barre, la troisième va venir croiser les deux autres barres et ainsi former une croix. Astucieux, n'est-il pas ?

Cliquez sur l'icône :



*,*::before,*:after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    

.menu_hamburger+label{

cursor: pointer;
position: relative;
margin: 5rem auto;
display: flex;
justify-content: center;
height: 60px;
width: 80px;
	}
  
	
.menu_hamburger+label span{

position: absolute;	
top: 50%;
margin-top: -5px;
width: 80px;
height: 10px;
background-color: #6753ea;
border-radius: 20px;
	
	}

.menu_hamburger+label span::before {
	

position: absolute;
content: '';
width: inherit;
height: inherit;
background-color: inherit;
top: -20px;
border-radius: inherit;	
	}

.menu_hamburger+label span::after {
	

position: absolute;
content: '';
width: inherit;
height: inherit;
background-color: inherit;
bottom: -20px;
border-radius: inherit;	
	}		
	
.menu_hamburger:checked+label span{

transform: rotate(45deg);
	
	}
	
.menu_hamburger:checked+label span::before{
	
top:unset
	
	}	
	
.menu_hamburger:checked+label span::after{
	
bottom: unset;
transform: rotate(-90deg);

}
	

Les ombres portées

Cette technique consiste en l'utilisation des ombres portées. Notre label sert de conteneur, tandis que l'élément span à l'intérieur constitue la barre centrale. Il nous suffit simplement d'ajouter une ombre portée négative pour la barre en haut et une ombre portée positive en ce qui concerne la barre du bas.



<input class="menu_hamburger" type="checkbox" id="votre-id">
<label for="votre-id"><span></span></label>




*,*::before,*:after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    

.menu_hamburger+label{

margin: 5rem auto;
display: flex;
justify-content: center;
align-items: center;
height: 60px;
width: 80px;
cursor: pointer;

	}
  
.menu_hamburger-box + label span {
  
border-radius: 20px;
background: #6753ea;
box-shadow: 0 -20px #6753ea, 0 20px #6753ea;
height: 10px;
width: inherit;
  
} 

	

Les dégradés

Nous allons à présent employer une autre technique, à savoir l'usage de la fonction linear-gradient().

Au lieu d'ajouter un arrière-plan uni identique à la barre centrale avec des pseudo-éléments, nous allons réaliser un dégradé linéaire qui va se répéter sur le label directement, de telle sorte qu'une moitié sera en couleur et l'autre moitié transparente.

Voici un graphique pour mieux comprendre la technique :

exemple menu hamburger css linear-gradient

Ce qui nous donne ceci :



<input class="menu_hamburger" type="checkbox" id="votre-id">
<label for="votre-id"></label>




*,*::before,*:after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    

.menu_hamburger+label{

cursor: pointer;
margin: 5rem auto;
display: flex;
width: 80px;
height: 80px;/*aspect-ratio:1*/
background: linear-gradient(#6753ea 50%, transparent 50%) 0 0/100% 40%;

	}
  
    

	

Maintenant, il nous faut créer la croix. L'idée ici est d'utiliser la fonction conic-gradient() et de la faire pivoter avec une transformation CSS.

Cliquez sur l'icône :



<input class="menu_hamburger" type="checkbox" id="votre_id">
<label for="votre_id"></label>

	



*{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    

.menu_hamburger+label{	

margin: 5rem auto;
display: flex;	
width: 80px;
height: 80px;/*aspect-ratio:1*/
background: linear-gradient(#6753ea 50%, transparent 50%) 0 0/100% 40%;
cursor:pointer;

}
	
.menu_hamburger:checked +label{

background:conic-gradient(from 90deg at 33% 33%, transparent 90deg, #6753ea 0) 100% 100%/60% 60%;
transform: translateZ(0) rotate(45deg);

}
	
	

Vous souhaitez ajouter des coins arrondis à votre icône ? Il va falloir ruser et ajouter quelques lignes de code supplémentaires.

En effet, nous allons nous servir des dégradés radiaux pour créer les coins arrondis. En fait, nous allons placer des ronds à droite et à gauche de chaque barre.

Voici un graphique pour vous aider à comprendre le concept :

exemple menu hamburger css conic-gradient

Cliquez sur l'icône ci-dessous :



*{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    

.menu_hamburger+label{	

margin: 5rem auto;
display: flex;
--taille-burger: 80px; 
width: var(--taille-burger);
height: var(--taille-burger);/*aspect-ratio: 1;*/
padding: calc(var(--taille-burger)*.1);
background:
radial-gradient(closest-side at 12.5% 25%,#6753ea 96%,#0000) 0 0/80% 40%,
linear-gradient(#6753ea 50%,#0000 0) top/80% 40% repeat-y;
cursor:pointer;

}
	
.menu_hamburger:checked+label {

background: 
radial-gradient(closest-side at 50% 12.5%,#6753ea 96%,#0000) top /20% 80% repeat-y,
radial-gradient(closest-side at 12.5% 50%,#6753ea 96%,#0000) left/80% 20% repeat-x,
conic-gradient(from 90deg at 33% 33%, #0000 90deg, #6753ea 0)100% 100%/60% 60% padding-box content-box;
transform: translateZ(0) rotate(45deg);

}
	
	

Avec Grid layout

Une autre solution consiste à utiliser le modèle de rendu des grilles. Pour obtenir nos trois barres, il nous suffit de créer trois éléments HTML (ici des éléments span), puis de définir notre grille en CSS.

Dès lors que l'on clique sur l'icône, on regroupe la première et la dernière barres au centre, on fait disparaître celle au centre, puis on applique une rotation.

Cliquez sur l'icône :



<input type="checkbox" id="grid">

<label for="grid">

<span></span>
<span></span>
<span></span>

</label>






*{box-sizing: border-box}

#grid+label{
margin:5rem auto;	
width:80px;
display:grid;
grid-template-rows: repeat(3,10px);
row-gap:.5rem;
	
	}

	
#grid+label span{

background-color: #6753ea;
border-radius: 20px;

	}
	
#grid:checked+label span{

grid-area: 2/1;

}

#grid:checked+label span:nth-child(2){

opacity: 0;

}

#grid:checked+label span:first-of-type{

transform:rotate(45deg)

}
			
#grid:checked+label span:last-of-type{

transform:rotate(-45deg);

}	



Animation de l'icône

Passons maintenant à l'animation de l'icône hamburger. Commençons par une simple rotation avec une transition.

Cliquez sur l'cône :



*,*::before,*::after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    
.menu_hamburger+label {

margin: 5rem auto;
display: flex;
justify-content: center;
align-items: center;	
height:60px;
width:80px;
cursor: pointer;

	
	}

.menu_hamburger+label span {

position: relative;
width: 80px;
height: 10px;
background-color: #6753ea;
transition: transform .4s;

}
	
.menu_hamburger+label span::before {
	
position: absolute;
content: '';
width: inherit;
height: inherit;
background:inherit;
top:-20px
	
	}

.menu_hamburger+label span::after {

position: absolute;
content: '';
top: 20px;
width: inherit;
height: inherit;
background:inherit;
	
	}

.menu_hamburger:checked+label span{

transform:rotate(45deg)
	
	}
	
.menu_hamburger:checked+label span::before{
	
	top: unset
	
	}
	
.menu_hamburger:checked+label span::after{
	
top: unset;
transform: rotate(-90deg);

	
	}

	

Un autre exemple où nous allons utiliser des transitions supplémentaires sur les pseudo-élements, ce qui va donner plus de mouvements à notre pictogramme. Cliquez sur l'icône ci-dessous :



*,*::before,*::after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
   

.menu_hamburger+label{
	
cursor: pointer;
width: 80px;
height: 60px;
display:flex;
align-items:center;
margin:5rem auto;
	
}
		
.menu_hamburger+label span {
	
background-color: #6753ea;
width: inherit;
height: 10px;
position: relative;
transition: background 10ms 300ms;
 
}
		
.menu_hamburger+label span::before, 
.menu_hamburger+label span::after {
	
transition: top 300ms 350ms, transform 300ms 50ms;
position: absolute;
background-color: #6753ea;
width: inherit;
height: inherit;
content: "";
	
}
	
.menu_hamburger+label span::before {
	
  top: -20px;
	
}
	
.menu_hamburger+label span::after {
	
  top: 20px;
	
}
	
.menu_hamburger:checked+label span {
	
  background: unset;
  
}
	
.menu_hamburger:checked+label span::after,
.menu_hamburger:checked+label span::before {

transition: top 300ms 50ms, transform 300ms 350ms;
top: 0;

}

.menu_hamburger:checked+label span::before {

  transform: rotate(45deg);
  
}

.menu_hamburger:checked+label span::after {

  transform: rotate(-45deg);
  
}	


Et si au lieu de transformer les trois barres pour former une croix, on utilisait deux barres pour obtenir une flèche de retour.



*,*::before,*::after{box-sizing: border-box}
  
/*input[type="checkbox"]*/.menu_hamburger {

position: absolute;
left: -100vw;

}
    

.menu_hamburger+label {

margin: 5rem auto;
display: flex;
justify-content: center;
align-items: center;	
height:60px;
width:80px;
cursor: pointer;

	
	}		
	
	
	
.menu_hamburger+label span{
	
transition: .3s;
position: relative;
width: 80px;
height: 10px;
background-color: #6753ea;


	}

.menu_hamburger+label span::before {
	
transition: .3s;
position: absolute;
content: '';
width: inherit;
height: inherit;
background:inherit ;
top:-20px
	
	}

.menu_hamburger+label span::after {

transition: .3s;
position: absolute;
content: '';
bottom: -20px;
width: inherit;
height: inherit;
background:inherit ;
	
	}

	
.menu_hamburger:checked+label span::before{

transform: translate3d(-20px,-17px,0px) rotate(-45deg) scaleX(.7);
top:0
	
	}
	
.menu_hamburger:checked+label span::after{
	
bottom:0;
transform: translate3d(-20px,17px,0) rotate(45deg) scaleX(.7);
	
	}	  
	

Il existe bon nombre de transitions. Vous trouverez en bas du tutoriel des liens renvoyant vers d'autres exemples.


Accessibilité

Il est préférable d'ajouter pour l'accessibilité l'attribut aria-label soit dans l'input soit dans le label et d'y ajouter une légende afin que les personnes utilisant des lecteurs d'écran sachent à quoi sert la case à cocher.



<input class="menu_hamburger" type="checkbox" id="votre_id">
<label for="votre_id" aria-label="Menu"></label>
	

Une autre solution plus efficace encore et qui conviendra à tout le monde, consiste à ajouter un terme comme "menu" par exemple dans le label. En effet, il se peut qu'une personne peu habituée à surfer ne connaisse pas la fonction de l'icône hamburger.

Il sera alors inutile d'ajouter l'attribut aria-label, le contenu à l'intérieur deviendrait redondant.



<input class="menu_hamburger" type="checkbox" id="votre_id">
<label for="votre_id">Menu</label>
	

N'oublions pas également les personnes qui utilisent la navigation au clavier avec la pseudo-classe :focus-visible. Nous allons par ailleurs rendre le menu accessible pour ceux qui souffrent de troubles de la vision avec la requête média CSS prefers-reduced-motion :



<input class="hamburger" type="checkbox" aria-label="Ouvrir menu" id="votre_id">
<label for="votre_id"><span></span></label>




*,*::before,*::after{box-sizing: border-box}	
	
input[type="checkbox"] {

position: absolute;
left: -100vw;

}	
	
.hamburger+label{
	
cursor: pointer;
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border-radius: 9999px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
margin: 5rem auto;	
}
		
.hamburger+label span {
	
background: #6753ea;
width: 40px;
height: 5px;
position: relative;

 
}
		
.hamburger+label span::before, 
.hamburger+label span::after {

  position: absolute;
  background: #6753ea;
  width: inherit;
  height: inherit;
  content: "";
}
	
.hamburger+label span::before {
  top: -10px;
}
.hamburger+label span::after {
  top: 10px;
}
	
.hamburger:checked+label span {
	
  background: transparent;
	
}
	
.hamburger:checked+label span::after,
.hamburger:checked+label span::before {

top: 0;
	
}
	
.hamburger:checked+label span::before {
	
  transform: rotate(45deg);
	
}
	
.hamburger:checked+label span::after {
	
  transform: rotate(-45deg);
	
}

.hamburger:focus-visible~label {

  outline: 2px solid #6753ea;
  outline-offset: 4px;
}
	
.hamburger:not(:focus-visible)~label
	{
    outline: none;
  }	

.hamburger:not(:focus-visible):focus~label{box-shadow: 0 0 0 4px hsl(248, 78%, 58%)}
	
	
/*on applique les transitions ici*/	
	
@media (prefers-reduced-motion: no-preference) {

.hamburger+label span {transition: background 10ms 300ms;}
.hamburger+label span::before, 
.hamburger+label span::after{transition: top 300ms 350ms, transform 300ms 50ms;}
.hamburger:checked+label span::after,
.hamburger:checked+label span::before {transition: top 300ms 50ms, transform 300ms 350ms;}	
	
.hamburger:focus-visible~label {transition: outline-offset .25s ease;}		
  
}


Maintenant que nous avons vu comment créer l'icône hamburger, il nous reste à créer le menu en lui-même.

Il existe plusieurs manières de construire ce menu. Nous pouvons par exemple mettre en place un contenu caché où se trouve les rubriques et qui survient avec un effet de slide lorsqu'on clique sur l'icône.

On peut également créer un effet de toggle, un menu pleine page (fullscreen), un simple effet de fondu... Vous l'aurez compris, nous avons de nombreuses solutions à notre disposition.

D'abord la structure HTML :



<input class="menu_hamburger" type="checkbox" id="votre_id" tabindex="0">
<label for="votre_id" aria-label="Menu"></label>

<nav>

<ul>
<li><a tabindex="0" href="#!">Rubrique 1</a></li>
<li><a tabindex="0" href="#!">Rubrique 2</a></li>
<li><a tabindex="0" href="#!">Rubrique 3</a></li>
<li><a tabindex="0" href="#!">Rubrique 4</a></li>
</ul>

</nav>


Dans ce code on retrouve l'icône hamburger ainsi que les rubriques au sein de l'élément nav. Cette base servira pour les exemples qui suivent.

Le slide est un classique. C'est sans doute l'approche la plus adéquate en terme d'expérience utilisateur. On cache le menu en utilisant les transformations CSS. Au moment du clic/tap sur l'icône, l'action de slide s'enclenche.

Dans ce dernier exemple, nous retrouvons le menu complet construit en "mobile first", c'est-à-dire que nous avons d'abord mis en place la version mobile avec un contenu caché sur la gauche et qui s'affiche avec un effet de slide.

Puis avec une requête media @media, nous avons ajusté le contenu du menu pour qu'il soit visible sur des écrans plus larges (à partir de 800px) et que nous avons placé sur le côté droit.