Header sticky avec changement de statut au scroll
by oilvier
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
<header class="header">
logo
</header>
<main>
<p><img src="//placehold.it/1200x500/c6e170/FFFFFF" alt=""></p>
<p><img src="//placehold.it/1200x500/92c46d/FFFFFF" alt=""></p>
<p><img src="//placehold.it/1200x500/297d7d/FFFFFF" alt=""></p>
</main>
SCSS
body {height:1500px; background-color:beige;}
img {max-width: 100%; height: auto;}
.header {position:relative; padding:20px; background-color:#c6e170; color:white; z-index:10;}
/* ==========================================================================
## Header fixe
========================================================================== */
/**
* Élément "fantôme" généré en JS qui prendra la place du header une fois qu'il sera fixé
* Cela évite d'appliquer un padding sur l'élément principal
*/
.header-placeholder {background-color:#c6e170;
.js & {display:none;}
}
.header {
/* On ajoute la classe via JavaScript */
&.is-sticky,
&.is-sticky-first {position:fixed; top:0; left:0; right:0; padding:15px 20px; background-color:white; color:black; transform:translate3d(0,0,0); box-shadow:0 0 5px rgba(0,0,0,.25); transition:background 0.15s ease-out, color 0.15s ease-out;
/* On affiche l'élément fantôme pour éviter un saut de la scrollbar suite à la disparition du flux de notre header */
& + .header-placeholder {display:block;}
}
}
JavaScript
/*===================================
= Header fixe =
===================================*/
var scrolling = false,
headerHeight = $('.header').outerHeight();
// On utilise requestAnimationFrame pour améliorer les performances
function requestStickyHeader() {
if(!scrolling) {
requestAnimationFrame(stickyHeader);
scrolling = true;
}
}
function stickyHeader() {
var scrollTopPosition = $(window).scrollTop(),
$header = $(".header"),
headerPosition = $header.outerHeight();
// On détecte si l'utilisateur a dépassé le haut du header à déplacer
if (scrollTopPosition > headerPosition ) {
// On ajoute la classe qui permet de coller le header
$header.addClass('is-sticky');
// Si la page a été ouverte avec une position de scroll avancée, on retirer la classe associée
if ($header.hasClass('is-sticky-first')) {
$header.removeClass('is-sticky-first');
}
} else if (scrollTopPosition < (headerPosition / 2) ) {
// Une fois que l'utilisateur est retourné en haut de l'écran, on annule le comportement
$header.removeClass('is-sticky');
}
if($('.header-placeholder').length) {
// On attribue la hauteur du header sur l'élément qui prend sa place
$('.header-placeholder').css('height', headerHeight);
}
// On remet à 0 pour appeler les prochains requestAnimationFrame
scrolling = false;
}
/**
* Au chargement, on vérifie la position de la page
* Si besoin, on ajoute une classe spécifique pour afficher le header
* ! Ce n'est pas la même classe que pour le scroll classique !
*/
if($(window).scrollTop() > headerHeight) {
$('.header').addClass('is-sticky-first');
}
if(!$('.header-placeholder').length) {
// On ajoute aussi un élément "fantôme" pour prendre le même espace que le header qui sort du flux
$('<div class="header-placeholder"></div>').insertAfter('.header').css('height', headerHeight);
}
// On lance notre fonction au load, resize et scroll
// Load : pour que le header apparaisse si on rafraichit au...