
Pas moyen d’empêcher le clignotement de l’entête, quand, lorsque je défile vers le bas, il arrive au seuil de déclenchement pour le passage à la version étroite.

En vidéo ça donne ceci :
J’ai testé à peu près tout ce que j’ai pu trouver sur le net pour régler ça, en particulier une pause de 200ms avant de basculer de classe côté javascript — celle qui contrôle l’aspect et la taille de l’entête — mais rien à faire, ça continue à clignoter dès que j’atteint le seuil, et quel que soit le-dit seuil ; très étrange…
Du coup je suis revenu à quelque chose de plus standard, sans changement d’aspect et j’ai conservé l’entête étroite avec un futur menu dépliant probablement vers la droite. Genre mobile first donc !
Et comme souvent, ça m’agaçait de pas trouver une solution et hop, le code qui fonctionne :
'use strict';
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
var breakpoint = null;
document.addEventListener('DOMContentLoaded', function () {
breakpoint = document.querySelector('.header').offsetHeight;
});
window.addEventListener('scroll', function () {
let header = document.querySelector('.header');
if (breakpoint > 0) {
if (window.pageYOffset >= breakpoint) {
sleep(200).then(() => {
header.classList.add('shrink');
breakpoint = header.offsetHeight;
});
} else if (window.pageYOffset < breakpoint) {
sleep(200).then(() => {
header.classList.remove('shrink');
breakpoint = header.offsetHeight;
});
}
}
});
Forcément si je change la hauteur de l’entête, la position de défilement de la page est modifiée en conséquence et ça je ne l’avais pas pris en compte…
C’est malin, maintenant j’hésite entre l’entête étroite en permanence ou le basculement pendant le défilement ; vous avez une préférence vous ?
À tester ici.
Et sur les conseils de biou et nicod un code « débouncé » :
'use strict';
let ensemble = {
breakpoint: null, // Height of current header, in pixels
timerId: null,
debounceFunction: function (func, delay) {
if (ensemble.timerId) {
clearTimeout(ensemble.timerId);
}
ensemble.timerId = setTimeout(func, delay);
},
doShrinkHeader: function () {
let header = document.querySelector('.header');
if (ensemble.breakpoint > 0) {
if (window.pageYOffset >= ensemble.breakpoint) {
header.classList.add('shrink');
ensemble.breakpoint = header.offsetHeight;
} else if (window.pageYOffset < ensemble.breakpoint) {
header.classList.remove('shrink');
ensemble.breakpoint = header.offsetHeight;
}
document.querySelector('html').style.scrollPaddingTop = `${ensemble.breakpoint + 24}px`;
}
},
};
// Get current height of header
document.addEventListener('DOMContentLoaded', () => ensemble.breakpoint = document.querySelector('.header').offsetHeight);
// Watch page scrolling and (un)shrink header if necessary
window.addEventListener('scroll', () => ensemble.debounceFunction(ensemble.doShrinkHeader, 200));
1 De Biou -
Ouais c’est assez chiant à faire ce genre d’effet. Est-ce que tu mesurais la distance de scroll? Si la hauteur de tes éléments change, ça perturbe ta mesure. Quand tu gères ça avec un on scroll, il faut aussi utiliser un debounce / throttling.
Est-ce que tu utilisais un intersection observer?
2 De nicod_ -
Ça répond pas à ta question, je sais ^^, mais moi je suis pas fan de ces entêtes qui restent collés en haut, d’autant que ça apporte des soucis si tu utilises des ancres dans la page : il faut décaler le scroll d’un certain delta (hauteur de l’entête), c’est casse bonbon.
Et sinon, +1 pour le debounce / throttling, pour éviter de faire tourner les ventilos à fond :)
3 De Franck -
« debounce / throttling », m’en vais m’enquérir de qu’est-ce-que-c’est-que-ce-truc :-)
Et puis trouver comment jouer avec « intersection observer » ; j’vous ai déjà dit que j’aimais bien essayer des trucs que je ne connais pas ?
Mais sur le fond, j’suis assez d’accord, une entête mobile-first, donc plutôt étroite (en hauteur) et baste…
Merci vous deux !
4 De Franck -
Ah y’est, c’est « débouncé » \o/
5 De Bernard -
Ah queue… je comprends pas pourquoi
haut de page
qui pointe sur l’idprelude
ben ne renvoie pas sur cette id (dans div class “header”)…Pitet que c’est parce que l’header devrait être déplié ??? Mébon c’est peut-être chez moi ?
6 De Franck -
Je suis au courant Bernard, un autre problème à régler, mais pas aujourd’hui, faut en garder pour les jours qui viennent ;-)
7 De Biou -
Content que ça ait pu t’aider ! IntersectionObserver c’est sympa mais l’API est un peu complexe. En théorie c’est la méthode la plus performante, mais pas de support IE11.