
Créer un Header Responsive avec Menu Burger en Framer Motion
Dans ce tutoriel, je vais vous apprendre à créer un header responsive avec un menu burger animé en utilisant Framer Motion et React. Ce composant va se comporter de manière fluide et s’adapter à différentes tailles d’écran.
Préparer le projet
Tout d'abord, vous devez avoir un projet React avec Framer Motion installé. Si ce n'est pas encore fait, vous pouvez l'ajouter avec cette commande :
npm install framer-motion
En plus de Framer Motion, j'utilise Lucide Icons pour l'icône du menu burger. Si vous ne l'avez pas encore installé, voici la commande pour l'ajouter à votre projet :
npm install lucide-react
Cela vous permettra d'utiliser l'icône de menu burger dans votre composant.
Créer le composant Header
Nous allons créer un composant Header avec un logo et un menu qui se transforme en menu burger lorsque l'écran devient petit.
"use client";
import { useState, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Menu } from "lucide-react";
import Link from "next/link";
// Éléments de la navigation
const navItems = [
{ text: "Accueil", href: "/" },
{ text: "À propos", href: "/about" },
{ text: "Services", href: "/services" },
{ text: "Contact", href: "/contact" },
];
export default function Header() {
const [isOpen, setIsOpen] = useState(false);
const menuRef = useRef(null);
// Fonction pour ouvrir ou fermer le menu
const toggleMenu = () => {
setIsOpen(!isOpen);
};
// Variants pour l'overlay
const overlayVariants = {
hidden: { opacity: 0 },
visible: { opacity: 0.2 },
};
// Variants pour l'animation du conteneur (staggerChildren appliqué ici)
const navVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.2,
duration: 0.6,
ease: "easeInOut",
},
},
};
// Variants pour chaque élément de la liste
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
};
return (
<header className="fixed left-0 top-0 z-50 flex w-full items-center justify-between bg-white px-6 py-2 shadow-md md:py-4">
{/* Logo à gauche */}
<Link href="/" className="text-2xl font-bold text-cyan-900">
Logo
</Link>
{/* Liens visibles uniquement sur écrans larges */}
<nav className="hidden items-center space-x-8 md:flex">
{navItems.map((item) => (
<Link
key={item.text}
href={item.href}
className="text-lg font-normal text-cyan-900 hover:text-cyan-600"
>
{item.text}
</Link>
))}
</nav>
{/* Bouton burger visible uniquement sur petits écrans */}
<button
onClick={toggleMenu}
aria-label="Ouvrir le menu"
className="flex flex-col items-center justify-center space-y-2 p-3 focus:outline-none xl:hidden"
>
<Menu size={32} color="black" />
</button>
{/* Overlay pour fermer le menu au clic */}
<AnimatePresence>
{isOpen && (
<motion.div
className="fixed inset-0 z-40 bg-black"
initial="hidden"
animate="visible"
exit="hidden"
variants={overlayVariants}
transition={{ duration: 0.4 }}
onClick={() => setIsOpen(false)}
/>
)}
</AnimatePresence>
{/* Menu latéral avec animation */}
<motion.nav
ref={menuRef}
initial={{ x: "100%", opacity: 0, scaleX: 0.6, rotateY: 90 }}
animate={{
x: isOpen ? "0%" : "100%",
opacity: isOpen ? 1 : 0,
scaleX: isOpen ? 1 : 0.6,
rotateY: isOpen ? 0 : 90,
}}
transition={{
duration: 0.6,
ease: "easeInOut",
}}
className="fixed right-0 top-0 z-50 flex h-full w-72 items-center justify-center bg-cyan-900 p-5 text-white shadow-lg sm:hidden"
aria-hidden={!isOpen}
role="navigation"
>
<motion.ul
variants={navVariants}
initial="hidden"
animate={isOpen ? "visible" : "hidden"}
className="flex flex-col items-center space-y-12"
>
{navItems.map((item) => (
<motion.li key={item.text} variants={itemVariants}>
<Link href={item.href} className="text-2xl font-normal">
{item.text}
</Link>
</motion.li>
))}
</motion.ul>
</motion.nav>
</header>
);
}
- Logo : À gauche, nous avons un simple lien avec le texte "Logo" pour simuler un logo.
- Menu sur grands écrans : Les liens de navigation sont visibles par défaut sur les écrans larges grâce à la classe hidden sm:flex.
- Bouton burger : Sur les petits écrans, le bouton burger (menu) devient visible avec la classe sm:hidden. Lorsque l'on clique dessus, il ouvre un menu latéral animé.
- Animation du menu burger : Le menu se slide depuis la droite avec une transition fluide, en utilisant Framer Motion pour gérer l'animation.

Alexis Pennel
Publié le 10 décembre 2024
Autres posts qui pourraient vous plaire
Composant de cartes avec skeleton loader en React.js et Tailwind CSS
Créer une animation de liste UL avec Framer Motion sur React et Next.js
Barre de recherche avec React et Framer Motion
Créez des Animations Fluides avec Framer Motion en React