Header Sticky Bootstrap 5

Extraits & Composants HTML 31/03/2026 15:00:00 AngularForAll.com
Bootstrap 5 Header Sticky Navigation Scroll Responsive Navbar Fixed Ombre Html Snippet

Header fixe Bootstrap 5 avec effet sticky au scroll, ombre progressive, logo responsive, navigation principale et bouton call-to-action.

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8" />
  <meta name="copyright" content="AngularForAll" />
  <meta name="author" content="AngularForAll" />
  <meta name="robots" content="noindex, nofollow" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="Cache-Control" content="public, max-age=604800" />
  <title>Snippets Stickyheader Bootstrap 5 2026 05011212 | AngularForAll</title>
<!-- Bootstrap 5 CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Bootstrap Icons -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
</head>
<body>

    <!-- ============================================================ -->
    <!-- COMPOSANT : STICKY HEADER -->
    <!-- ============================================================ -->

    <!-- Header Principal - Visible par défaut -->
    <header id="mainHeader" class="sticky-header navbar navbar-expand-lg navbar-light bg-white shadow-sm py-3">
        <div class="container">

            <!-- Logo -->
            <a class="navbar-brand d-flex align-items-center" href="#">
                <div class="bg-primary text-white rounded-3 p-2 me-2">
                    <i class="bi bi-shop fs-5"></i>
                </div>
                <div>
                    <span class="fw-bold fs-4">Shop</span><span class="text-primary fw-bold fs-4">Sticky</span>
                </div>
            </a>

            <!-- Bouton hamburger mobile -->
            <div class="d-flex align-items-center gap-2">
                <!-- Panier (visible sur mobile) -->
                <button class="btn btn-outline-primary btn-sm rounded-pill position-relative d-lg-none me-2">
                    <i class="bi bi-cart3"></i>
                    <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">3</span>
                </button>

                <button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse" aria-label="Toggle navigation"
                        data-bs-target="#headerNav" aria-controls="headerNav" aria-expanded="false">
                    <i class="bi bi-list fs-2"></i>
                </button>
            </div>

            <!-- Navigation -->
            <div class="collapse navbar-collapse" id="headerNav">
                <ul class="navbar-nav mx-auto mb-2 mb-lg-0">
                    <li class="nav-item">
                        <a class="nav-link active fw-semibold px-3" href="#">Accueil</a>
                    </li>
                    <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle fw-semibold px-3" href="#" role="button"
                           data-bs-toggle="dropdown" aria-expanded="false">
                            Produits
                        </a>
                        <ul class="dropdown-menu shadow border-0 rounded-3">
                            <li><a class="dropdown-item" href="#"><i class="bi bi-laptop me-2"></i>Électronique</a></li>
                            <li><a class="dropdown-item" href="#"><i class="bi bi-handbag me-2"></i>Mode</a></li>
                            <li><a class="dropdown-item" href="#"><i class="bi bi-house-heart me-2"></i>Maison</a></li>
                            <li><hr class="dropdown-divider"></li>
                            <li><a class="dropdown-item" href="#"><i class="bi bi-stars me-2"></i>Promotions</a></li>
                        </ul>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link fw-semibold px-3" href="#">Collections</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link fw-semibold px-3" href="#">À propos</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link fw-semibold px-3" href="#">Contact</a>
                    </li>
                </ul>

                <!-- Actions droite -->
                <div class="d-flex align-items-center gap-3">
                    <!-- Barre de recherche desktop -->
                    <div class="input-group input-group-sm d-none d-lg-flex" style="max-width: 200px;">
                        <span class="input-group-text bg-light border-0">
                            <i class="bi bi-search text-muted"></i>
                        </span>
                        <input type="text" class="form-control bg-light border-0" placeholder="Rechercher...">
                    </div>

                    <!-- Wishlist -->
                    <button class="btn btn-link text-dark position-relative d-none d-lg-block"
                            data-bs-toggle="tooltip" data-bs-placement="bottom" title="Favoris">
                        <i class="bi bi-heart fs-5"></i>
                        <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">5</span>
                    </button>

                    <!-- Panier desktop -->
                    <button class="btn btn-primary btn-sm rounded-pill position-relative d-none d-lg-flex align-items-center px-3">
                        <i class="bi bi-cart3 me-1"></i> Panier
                        <span class="badge bg-light text-primary ms-2 rounded-pill">3</span>
                    </button>

                    <!-- Profil utilisateur -->
                    <div class="dropdown d-none d-lg-block">
                        <button class="btn btn-link text-dark dropdown-toggle d-flex align-items-center" aria-label="Profil utilisateur"
                                data-bs-toggle="dropdown" aria-expanded="false">
                            <div class="bg-secondary bg-opacity-10 rounded-circle p-2 me-1">
                                <i class="bi bi-person fs-5"></i>
                            </div>
                        </button>
                        <ul class="dropdown-menu dropdown-menu-end shadow border-0 rounded-3">
                            <li><a class="dropdown-item" href="#"><i class="bi bi-person me-2"></i>Mon Profil</a></li>
                            <li><a class="dropdown-item" href="#"><i class="bi bi-box me-2"></i>Mes Commandes</a></li>
                            <li><a class="dropdown-item" href="#"><i class="bi bi-gear me-2"></i>Paramètres</a></li>
                            <li><hr class="dropdown-divider"></li>
                            <li><a class="dropdown-item text-danger" href="#"><i class="bi bi-box-arrow-right me-2"></i>Déconnexion</a></li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </header>

    <!-- Header Compact - Apparaît au scroll vers le haut -->
    <header id="compactHeader" class="sticky-header-compact navbar navbar-expand-lg navbar-dark bg-dark shadow-lg py-2">
        <div class="container">
            <a class="navbar-brand d-flex align-items-center" href="#">
                <div class="bg-primary text-white rounded-3 p-1 me-2">
                    <i class="bi bi-shop fs-6"></i>
                </div>
                <span class="fw-bold text-white">ShopSticky</span>
            </a>

            <button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse"
                    data-bs-target="#compactNav" aria-controls="compactNav" aria-expanded="false" aria-label="Toggle navigation">
                <i class="bi bi-list text-white fs-2"></i>
            </button>

            <div class="collapse navbar-collapse" id="compactNav">
                <ul class="navbar-nav mx-auto mb-2 mb-lg-0">
                    <li class="nav-item"><a class="nav-link text-white-50 fw-semibold px-2" href="#">Accueil</a></li>
                    <li class="nav-item"><a class="nav-link text-white-50 fw-semibold px-2" href="#">Produits</a></li>
                    <li class="nav-item"><a class="nav-link text-white-50 fw-semibold px-2" href="#">Collections</a></li>
                    <li class="nav-item"><a class="nav-link text-white-50 fw-semibold px-2" href="#">Contact</a></li>
                </ul>

                <div class="d-flex align-items-center gap-2">
                    <div class="input-group input-group-sm" style="max-width: 180px;">
                        <input type="text" class="form-control bg-dark border-secondary text-white" placeholder="Recherche..." aria-label="Recherche">
                        <button class="btn btn-primary btn-sm" aria-label="Rechercher">
                            <i class="bi bi-search"></i>
                        </button>
                    </div>
                    <button class="btn btn-primary btn-sm rounded-pill position-relative">
                        <i class="bi bi-cart3"></i>
                        <span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">3</span>
                    </button>
                </div>
            </div>
        </div>
    </header>

    <!-- ============================================================ -->
    <!-- CONTENU DÉMO DE LA PAGE -->
    <!-- ============================================================ -->

    <main>
        <!-- Hero Section -->
        <section class="bg-primary text-white py-5">
            <div class="container py-5 text-center">
                <i class="bi bi-arrow-down-up fs-1 mb-3"></i>
                <h1 class="display-4 fw-bold">Sticky Header Intelligent</h1>
                <p class="lead mb-0">Faites défiler la page pour voir le header se transformer !</p>
            </div>
        </section>

        <!-- Démo du comportement -->
        <section class="py-5">
            <div class="container">
                <div class="row g-4">
                    <div class="col-md-4">
                        <div class="card h-100 shadow-sm text-center p-4">
                            <i class="bi bi-eye fs-1 text-primary"></i>
                            <h5 class="mt-3">État Visible</h5>
                            <p class="text-muted">Header complet avec logo, navigation et actions</p>
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="card h-100 shadow-sm text-center p-4">
                            <i class="bi bi-arrow-bar-up fs-1 text-success"></i>
                            <h5 class="mt-3">État Compact</h5>
                            <p class="text-muted">Apparaît quand on scrolle vers le haut</p>
                        </div>
                    </div>
                    <div class="col-md-4">
                        <div class="card h-100 shadow-sm text-center p-4">
                            <i class="bi bi-phone fs-1 text-warning"></i>
                            <h5 class="mt-3">Responsive</h5>
                            <p class="text-muted">Adapté à tous les écrans</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Contenu factice pour le scroll -->
        <section class="bg-light py-5">
            <div class="container">
                <div class="row g-4">
                    <div class="col-md-3">
                        <div class="card shadow-sm">
                            <div class="card-body text-center py-5">
                                <i class="bi bi-image fs-1 text-muted"></i>
                                <h6 class="mt-2">Produit 1</h6>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card shadow-sm">
                            <div class="card-body text-center py-5">
                                <i class="bi bi-image fs-1 text-muted"></i>
                                <h6 class="mt-2">Produit 2</h6>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card shadow-sm">
                            <div class="card-body text-center py-5">
                                <i class="bi bi-image fs-1 text-muted"></i>
                                <h6 class="mt-2">Produit 3</h6>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <div class="card shadow-sm">
                            <div class="card-body text-center py-5">
                                <i class="bi bi-image fs-1 text-muted"></i>
                                <h6 class="mt-2">Produit 4</h6>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Texte additionnel pour le scroll -->
                <div class="mt-5 p-5 bg-white rounded-3 shadow-sm">
                    <h3>Faites défiler vers le haut pour voir le header compact</h3>
                    <p class="text-muted">
                        Le header principal disparaît quand vous descendez, et un header compact
                        apparaît quand vous remontez pour une navigation rapide.
                    </p>
                    <hr>
                    <p class="text-muted">
                        Continuez à faire défiler pour tester le comportement. Le header s'adapte
                        intelligemment à votre navigation pour optimiser l'espace d'écran.
                    </p>
                </div>

                <!-- Plus de contenu pour le scroll -->
                <div class="row mt-4 g-4">
                    <div class="col-12">
                        <div class="p-4 bg-white rounded-3 shadow-sm">
                            <h4>Section additionnelle</h4>
                            <p class="text-muted mb-0">Contenu pour allonger la page et tester le scroll.</p>
                        </div>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <!-- Footer simple -->
    <footer class="bg-dark text-white py-4">
        <div class="container text-center">
            <p class="mb-0">&copy; 2024 ShopSticky - Composant StickyHeader</p>
        </div>
    </footer>

    <!-- Indicateur d'état du header -->
    <div id="headerState" class="position-fixed bottom-0 start-0 m-3">
        <div class="badge bg-success fs-6 px-3 py-2 shadow">
            Header: <span id="stateText">Visible</span>
        </div>
    </div>

    <!-- Bootstrap 5 JS -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>

    <script>
        // ============================================================
        // STICKY HEADER - Logique de comportement
        // ============================================================

        document.addEventListener('DOMContentLoaded', function() {

            // Éléments du DOM
            const mainHeader = document.getElementById('mainHeader');
            const compactHeader = document.getElementById('compactHeader');
            const stateText = document.getElementById('stateText');

            // Variables de suivi
            let lastScrollY = window.scrollY;
            let scrollDirection = 'none';
            let isScrolling = false;
            const scrollThreshold = 50; // Seuil minimal de scroll
            const headerHeight = mainHeader.offsetHeight;

            // Initialisation : cacher le header compact
            compactHeader.style.transform = 'translateY(-100%)';
            compactHeader.style.transition = 'transform 0.3s ease';
            mainHeader.style.transition = 'transform 0.3s ease, opacity 0.3s ease';

            // Fonction de mise à jour des headers
            function updateHeaders() {
                const currentScrollY = window.scrollY;

                // Déterminer la direction du scroll
                if (currentScrollY > lastScrollY + 5) {
                    scrollDirection = 'down';
                } else if (currentScrollY < lastScrollY - 5) {
                    scrollDirection = 'up';
                }

                // Si en haut de la page
                if (currentScrollY < headerHeight) {
                    // Afficher le header principal, cacher le compact
                    mainHeader.style.transform = 'translateY(0)';
                    mainHeader.style.opacity = '1';
                    compactHeader.style.transform = 'translateY(-100%)';
                    updateState('Visible (Haut de page)');
                }
                // Si on descend
                else if (scrollDirection === 'down' && currentScrollY > scrollThreshold) {
                    // Cacher le header principal
                    mainHeader.style.transform = 'translateY(-100%)';
                    mainHeader.style.opacity = '0';
                    // Cacher aussi le compact quand on descend
                    compactHeader.style.transform = 'translateY(-100%)';
                    updateState('Caché (Scroll vers le bas)');
                }
                // Si on remonte
                else if (scrollDirection === 'up' && currentScrollY > scrollThreshold) {
                    // Garder le principal caché
                    mainHeader.style.transform = 'translateY(-100%)';
                    mainHeader.style.opacity = '0';
                    // Afficher le compact
                    compactHeader.style.transform = 'translateY(0)';
                    updateState('Compact (Scroll vers le haut)');
                }

                lastScrollY = currentScrollY;
                isScrolling = false;
            }

            // Mise à jour de l'indicateur d'état
            function updateState(state) {
                stateText.textContent = state;
            }

            // Optimisation avec requestAnimationFrame
            let ticking = false;

            window.addEventListener('scroll', function() {
                if (!ticking) {
                    window.requestAnimationFrame(function() {
                        if (!isScrolling) {
                            isScrolling = true;
                            updateHeaders();
                        }
                        ticking = false;
                    });
                    ticking = true;
                }
            });

            // Initialiser les tooltips Bootstrap
            const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
            tooltipTriggerList.map(function(tooltipTriggerEl) {
                return new bootstrap.Tooltip(tooltipTriggerEl);
            });

            // Ajuster au redimensionnement
            window.addEventListener('resize', function() {
                const newHeaderHeight = mainHeader.offsetHeight;
                if (window.scrollY < newHeaderHeight) {
                    mainHeader.style.transform = 'translateY(0)';
                    mainHeader.style.opacity = '1';
                    compactHeader.style.transform = 'translateY(-100%)';
                }
            });
        });
    </script>

    <style>
        /* ============================================================ */
        /* Styles spécifiques au StickyHeader */
        /* ============================================================ */

        /* Header principal */
        .sticky-header {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            z-index: 1030;
            will-change: transform, opacity;
        }

        /* Header compact */
        .sticky-header-compact {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            z-index: 1029;
            will-change: transform;
        }

        /* Animation des liens de navigation */
        .nav-link {
            position: relative;
            transition: color 0.3s ease;
        }

        .nav-link::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 50%;
            width: 0;
            height: 2px;
            background: var(--bs-primary);
            transition: all 0.3s ease;
            transform: translateX(-50%);
        }

        .nav-link:hover::after,
        .nav-link.active::after {
            width: 80%;
        }

        /* Effet de pulsation sur le badge panier */
        @keyframes cartPulse {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.2); }
        }

        .badge.rounded-pill.bg-danger {
            animation: cartPulse 2s ease-in-out infinite;
        }

        /* Transition smooth pour le header compact */
        .sticky-header-compact .nav-link {
            transition: color 0.3s ease;
        }

        .sticky-header-compact .nav-link:hover {
            color: white !important;
        }

        /* Responsive */
        @media (max-width: 991.98px) {
            .sticky-header .navbar-collapse,
            .sticky-header-compact .navbar-collapse {
                background: inherit;
                padding: 1rem;
                border-radius: 0.5rem;
                margin-top: 0.5rem;
            }

            .sticky-header .navbar-collapse {
                background: white;
                box-shadow: 0 4px 6px rgba(0,0,0,0.1);
            }

            .sticky-header-compact .navbar-collapse {
                background: var(--bs-dark);
            }
        }
    </style>

</body>
</html>

Télécharger le fichier source

Partager