Sticky Header Detection
Header sticky piloté par l'attribut data-stuck : à 10 px de scroll, fond plus opaque, ombre portée et logo accentué — transition CSS pure, aucune dépendance.
Vous aurez accès à la démo interactive avec un compte gratuit.
Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Navigation comprend 36 effets, dont 4 gratuits. Découvrir la catégorie →
3 exemples d'usage



Comment ça marche
L'effet écoute l'événement scroll nativement sur l'élément #scrollArea — sans IntersectionObserver. Dès que le scrollTop du conteneur dépasse 10 px, le script pose data-stuck="true" sur #stickyNav ; en deçà, il repasse à "false". Un seul setAttribute par événement scroll, aucun debounce.
La réponse visuelle est entièrement pilotée par CSS via le sélecteur d'attribut [data-stuck=true]. Le JS ne touche ni à des classes ni à du style inline : il écrit un attribut, la feuille de style réagit. Ce découplage permet de redéfinir l'aspect « collé » sans jamais modifier la logique de détection.
À l'état collé, trois transitions CSS de 0,3 s se déclenchent simultanément : l'arrière-plan monte de rgba(18,18,26,0.8) à rgba(18,18,26,0.95), une box-shadow de 20 px apparaît, et la bordure basse passe de transparent à var(--border). Le logo reçoit en plus transform: scale(1.05) et change de couleur vers #6366f1 — signal discret que la navigation est maintenant ancrée.
Le conteneur combine overflow: hidden et position: relative ; la nav est en position: absolute — elle ne déborde jamais. Un backdrop-filter: blur(10 px) constant donne au header un aspect verre dépoli même avant le premier pixel de scroll, rendant l'ensemble autonome et intégrable dans n'importe quelle mise en page.
Accessibilité
- prefers-reduced-motion absent : la
transition: .3ssur.sticky-navs'exécute sans consulter la préférence système. Pour les utilisateurs sensibles au mouvement, enveloppez les transitions dans@media (prefers-reduced-motion: no-preference). - Aucun
roleniaria-labelsur le header : en production, ajoutezrole="navigation"et unaria-labeldescriptif sur l'élément de navigation. - L'attribut
data-stuckest un hook CSS pur, non annoncé aux technologies d'assistance — le changement visuel est décoratif et ne véhicule pas d'état fonctionnel. - Les liens de navigation sont des
<span>dans la démo : remplacez-les par des<a>pour que la navigation au clavier et les lecteurs d'écran fonctionnent correctement. - Contraste : le logo passe en
#6366f1sur fond#12121aau scroll — ratio ≈ 4,5:1, à la limite du seuil WCAG AA pour le texte de petite taille ; vérifiez votre couleur brand.
Compatibilité navigateur
Requiert scroll event, sélecteurs d'attribut CSS et backdrop-filter — les deux premiers sont universels depuis IE9+ ; backdrop-filter est supporté dans tous les navigateurs modernes.
Si <code>backdrop-filter</code> n'est pas supporté, le header s'affiche avec son fond plein — aucune erreur JS, la détection de scroll fonctionne normalement.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="sticky-header-demo" id="stickyDemo">
<div class="sticky-nav" id="stickyNav">
<span class="nav-logo-mini">Brand</span>
<div class="nav-links-mini">
<span>Home</span>
<span>About</span>
<span>Contact</span>
</div>
</div>
<div class="scroll-area" id="scrollArea">
<div class="scroll-content">
<!-- contenu scrollable -->
</div>
</div>
</div>
HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
| s.scrollTop > 10 | 10 | Seuil en pixels au-delà duquel data-stuck passe à true. Remplacez 10 par 0 pour déclencher dès le premier pixel, ou 50–80 si un hero occupe toute la hauteur visible. |
| transition: .3s | .3s | Durée de toutes les transitions du header (fond, ombre, bordure). Passez à 0s pour un snap instantané ou 0.5s pour une fondu plus doux. |
| rgba(18, 18, 26, .8) | alpha 0.8 | Opacité du fond nav à l'état initial (non collé). Montez à 1 pour un fond plein dès le départ, descendez à 0.4 pour plus de transparence. |
| rgba(18, 18, 26, .95) | alpha 0.95 | Opacité du fond nav à l'état collé (data-stuck=true). Adaptez la couleur de base à votre palette brand. |
| box-shadow: rgba(0,0,0,.3) 0 4px 20px | 4px / 20px | Ombre portée à l'état collé. Réduisez la taille (2px / 8px) pour un rendu subtil, supprimez entièrement pour un effet 100 % couleur. |
| color: #6366f1 | #6366f1 | Couleur du logo quand le header est collé. Remplacez par votre couleur primaire pour un signal de branding discret. |
| backdrop-filter: blur(10px) | 10px | Flou d'arrière-plan constant du header. Réduisez à 4px pour un effet plus léger, supprimez la propriété pour économiser du GPU sur des appareils bas de gamme. |
FAQ
scroll classique qui lit scrollTop > 10. L'IntersectionObserver cible le viewport global ; ici la zone scrollable est un conteneur interne, ce qui rend le scroll event plus direct et plus fiable dans ce contexte.#scrollArea par window.addEventListener('scroll', …) et comparez window.scrollY > 10. Le reste — attribut data-stuck et CSS — reste identique. Passez le header en position: fixed et retirez overflow: hidden du conteneur parent.s.dispatchEvent(new Event('scroll')) pour forcer une première évaluation de scrollTop. Cela garantit que data-stuck est correct même si la page est rechargée à mi-scroll ou si le conteneur a déjà un offset initial.