Créer une barre de navigation avec un indicateur animé

Vous avez toujours voulu faire une barre de navigation dynamique avec un indicateur qui glisse tout doucement en-dessous de la nouvelle page sur laquelle vous êtes ? Cette barre de navigation est exactement ce qu'il vous faut !
1ère étape : le code HTML
Pour commencer, créons le code HTML qui nous permettra de mettre en place notre barre de navigation.
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Testimonials</a>
<a href="#">Blog</a>
<a href="#">Contact</a>
</nav>
Rien de bien difficile à comprendre ici. Nous avons une balise <nav></nav>
regroupant plusieurs liens. Ajoutons leur une classe .nav-item
pour que nos différents liens soient plus stylisés. Nous créerons ensuite une classe avec ce même nom afin de mettre quelques propriétés.
<nav>
<a href="#" class="nav-item is-active">Home</a>
<a href="#" class="nav-item">About</a>
<a href="#" class="nav-item">Testimonials</a>
<a href="#" class="nav-item">Blog</a>
<a href="#" class="nav-item">Contact</a>
</nav>
Notez que nous avons également ajouté une classe .is-active
afin que la page en cours soit affichée de manière différente. Il s'agit d'un repère visuel qui est très intéressant.
2ème étape : le code CSS
Pour notre style, nous partons sur un code très simple. Suivez donc les commentaires pour vous repérer sur ce que nous faisons.
/* On fait en sorte que chaque élément contienne sa marge interne avec box-sizing et on retire les traits qui sont par défaut sur les liens */
* {
box-sizing: border-box;
text-decoration: none;
}
/* On modernise notre balise de navigation avec une petite ombre. On mets tous les éléments du menu les uns bien à côté des autres avec flexbox (display: flex) */
nav {
background-color: #fff;
padding: 0 20px;
border-radius: 40px;
box-shadow: 0 10px 40px rgba(159, 162, 177, .8);
display: flex;
overflow: hidden;
overflow-x: auto;
position: relative;
}
/* On stylise chaque élément */
.nav-item {
color: #83818c;
font-family: arial, sans-serif;
padding: 20px;
margin: 0 6px;
position: relative;
}
/* Ici on met juste un petit élément avant chaque élément pour le rendre plus beau visuellement */
.nav-item:before {
content: "";
position: absolute;
bottom: -6px;
background-color: #dfe2ea;
height: 5px;
width: 100%;
border-radius: 8px 8px 0 0;
left: 0;
transition: .3s;
}
/* Avec les dernières nouveautés de CSS, on peut changer les propriétés des éléments selon des conditions avec not */
.nav-item:not(.is-active):hover:before {
bottom: 0;
}
.nav-item:not(.is-active):hover {
color: #333;
}
/* Stylisons notre indicateur */
.nav-indicator {
position: absolute;
left: 0;
bottom: 0;
height: 5px;
transition: .4s;
border-radius: 8px 8px 0 0;
}
3ème étape : Finaliser la partie HTML
Avoir un menu : c'est bon ! Mais essayons maintenant de le moderniser grâce à un indicateur qui fait un mouvement selon la page que nous consultons.
Pour réaliser ceci, commençons par ajouter un élément HTML grâce à la balise <span></span>
afin de mettre à l'intérieur de notre barre de navigation un élément qui bougera selon notre page actuelle.
<nav>
<a href="#" class="nav-item is-active">Home</a>
<a href="#" class="nav-item">About</a>
<a href="#" class="nav-item">Testimonials</a>
<a href="#" class="nav-item">Blog</a>
<a href="#" class="nav-item">Contact</a>
<span class="nav-indicator"></span>
</nav>
Nous avons pratiquement fini notre HTML ! Terminons en ajoutant des données récupérables par notre code JavaScript : il suffit pour cela d'utiliser des attributs data
en précisant le nom que nous voulons :
<nav>
<a href="#" class="nav-item is-active" data-active-color="orange" data-target="Home">Home</a>
<a href="#" class="nav-item" data-active-color="green" data-target="About">About</a>
<a href="#" class="nav-item" data-active-color="blue" data-target="Testimonials">Testimonials</a>
<a href="#" class="nav-item" data-active-color="red" data-target="Blog">Blog</a>
<a href="#" class="nav-item" data-active-color="rebeccapurple" data-target="Contact">Contact</a>
<span class="nav-indicator"></span>
</nav>
Notre code est terminé ! On passe maintenant au JavaScript.
4ème étape : le code JavaScript
Pour commencer, il est très important de sélectionner notre indicateur et chacun de nos éléments :
const indicator = document.querySelector('.nav-indicator');
const items = document.querySelectorAll('.nav-item');
Une fois que nos éléments ont été récupérés, nous allons essayer de détecter les événéments. Ce qui nous intéresse surtout est l'événement clic (click - en anglais).
La propriété JavaScript
querySelectorAll
retourne un tableau qui contient pour chaque élément un de nos items.
Il ne reste donc qu'à ce que nous utilisions une boucle forEach
afin d'attacher l'événement au clic grâce à addEventListener
en disant que nous souhaitons appeler la fonction handleIndicator
.
Cette nouvelle fonction handleIndicator
nous permettra de détecter le lien qui a été cliqué pour bouger l'indicateur (indicator).
const indicator = document.querySelector('.nav-indicator');
const items = document.querySelectorAll('.nav-item');
function handleIndicator(el) {
}
items.forEach((item, index) => {
item.addEventListener('click', e => {
handleIndicator(e.target)
});
item.classList.contains('is-active') && handleIndicator(item);
});
Il ne nous reste plus qu'une seule chose à faire : créer la fonction handleIndicator
.
const indicator = document.querySelector('.nav-indicator');
const items = document.querySelectorAll('.nav-item');
function handleIndicator(el) {
// Boucler sur items -> retirer la classe "is-active"
items.forEach(item => {
item.classList.remove('is-active');
item.removeAttribute('style');
})
const elementColor = el.dataset.activeColor;
const target = el.dataset.target;
// Styliser l'indicateur
indicator.style.width = `${el.offsetWidth}px`;
indicator.style.backgroundColor = elementColor;
indicator.style.left = `${el.offsetLeft}px`;
// Ajout la classe is-active
el.classList.add('is-active');
el.style.color = elementColor;
}
items.forEach((item, index) => {
item.addEventListener('click', e => {
handleIndicator(e.target)
});
item.classList.contains('is-active') && handleIndicator(item);
});
Voici ce que nous faisons pour chaque élément cliqué :
- On retire la classe
.is-active
pour tous les éléments : on réinitialise ici le menu ; - On récupére la couleur de l'item cliqué avec
dataset
qui nous permet de lire l'attributdata
; - On profite de cette couleur pour définir le style de notre indicateur (indicator) ;
- On ajoute au final la classe
.is-active
sur l'élément de la page actuelle.
Et le tour est joué !
Si vous voulez en apprendre plus, n'hésitez pas à suivre nos cours dédiés à JavaScript ou à React (si vous connaissez bien le JavaScript) pour profiter à 100% de votre tout nouveau menu réalisé dans cet article !