Menu fixe mais flottant selon la scrollbar (JS + CSS)

Photo of author
Écrit par Mimie

Se sentir libre de concilier "vie privée" et "vie numérique" sans intrusion.

Ma page Facebook

Certains ne comprennent peut-être pas ce dont je veux parler par « menu fixe mais flottant selon la scrollbar », en fait je fais référence au nouveau menu dans Gmail qui est figé en haut mais suit la scrollbar lorsque nous descendons l’ascenseur.
Cet effet permet d’avoir toujours à disposition le menu où que nous soyons dans la lecture de nos mails.

Ça semble anodin au premier abord pour la plupart des gens, un peu de CSS, un petit « position: fixed » et le tour est joué ? hé bien non, c’est plus fort que ça, car au départ le menu est incrusté et c’est seulement lorque la scrollbar atteint un point précis (ici lorsque le haut de la fenêtre atteint le menu) que le menu devient flottant, c’est donc dynamique, à comprendre qu’il va falloir utiliser du JavaScript.

Ce menu m’a intrigué dès le départ car je ne savais pas moi-même réaliser un tel effet, jusqu’au jour où j’en ai eu besoin pour l’affichage d’un deck de type « Commander » sur MS.

Démo

En effet au niveau de la vue d’un deck, le survol de la souris sur le nom d’une carte fait afficher l’image de celle-ci sur le côté gauche. Le problème c’est que la quantité de cartes d’un deck « Commander » fait que l’image ne devient plus visible lorsque nous scrollons vers le bas pour voir l’intégralité des cartes. D’où l’idée de rendre flottante l’image de la carte lorsque la scrollbar tente de la masquer.

Code

Finalement c’est assez simple à comprendre et donc à mettre en place.

CSS

2 astuces pour améliorer votre anonymat en ligne

1/ Pensez à l'utilisation d'un VPN : une application VPN va changer votre adresse IP pour simuler celle de n'importe quel pays. Vous pourrez donc accéder à n'importe quel contenu, même celui qui est géo-restreint. Ce logiciel chiffre aussi votre trafic internet pour éliminer les malwares et les risques de piratage.
2/ Pensez à utiliser un gestionnaire de mots de passe : Il va enregistrer vos mots de passe (compliqués) pour les insérer automatiquement pour vous, et il peut vous générer des mots de passe compliqués aléatoires (versions déclinables pour téléphones et ordinateurs).
L'offre NordVPN cumule les 2 avantages

Votre élément (menu, image, bandeau, div, etc.) a rendre flottant a par défaut une position « relative » par rapport à son conteneur, cette position devra passée à « fixed » au moment où nous le choisirons, dans notre cas lorsque la scrollbar tentera de masquer notre élément.

Le changement d’état de notre élement se fera par le biais d’une classe CSS, appliquée par du JavaScript, la voici :

votre_menu_ou_votre_image_ou_votre_element.floatable {
 position: fixed;
 top: 10px; // non-obligatoire
 }

JS

Pour détecter qu’il est temps de changer la position de notre élément, il faut connaître le positionnement de la scrollbar et la comparer au positionnement de notre élément. Pour cela j’utilise la fonction $(window).scroll() de jQuery.
Voici le mécanisme à mettre en place :

// listen for scroll
 var positionElementInPage = $('#votre_menu_ou_votre_image_ou_votre_element').offset().top;
 $(window).scroll(
 function() {
 if ($(window).scrollTop() >= positionElementInPage) {
 // fixed
 $('#votre_menu_ou_votre_image_ou_votre_element').addClass("floatable");
 } else {
 // relative
 $('#votre_menu_ou_votre_image_ou_votre_element').removeClass("floatable");
 }
 }
 );

Lorsque nous descendons l’image nous suit et reste visible, lorsque nous remontons, elle se recale à l’endroit du départ si nous dépassons son emplacement d’origine.

Sources

Si mes explications ne sont pas claires, voici un fichier d’exemple : menu_fixe_mais_flottant.html.

Catégories Web

Maquillez votre adresse IP

Être anonyme sur internet

nouvelle banniere maison nordvpn

114 réflexions au sujet de “Menu fixe mais flottant selon la scrollbar (JS + CSS)”

  1. J’ai regardé rapidement, il ne devrait pas avoir de position fixed dans ton css pour ton menu en tout . La class qui fixed le menu est à appelé avec le bout de code jQuery mis plus haut ..

  2. Mimie, mille merci pour cette précision, pas évident de s’en sortir au début.
    J’ai déplacé le javascript et je ne vois pourtant aucun changement ?

  3. Lut Vydja, ton javascript doit être placé avant la fermeture de la balise body (tout en bas de page) et non tout au début …

  4. Je ne vois pas ton code, par contre je suis sur ton blog, je regarde et te redis si je trouve l’erreur
    ;D

  5. J’ai envoyé un message plus haut où je donnais tout mon code, mais je ne sais pas s’il est passé.
    J’ai finalement réussi à enlever les caractères spéciaux affichés sur la page.
    Je souhaiterais simplement de l’aide pour ce qui est du menu fixe.
    Désolée pour le nombre de messages ! 😉

  6. Tu as du surement laissé un caractère inattendu.. Regarde ce que tu as écrit. Tu as peu être oublier de fermer une balise ou quelque chose de ce genre. .. Je peux voir le bug ?

  7. Rebonjour,

    j’ai fait une grosse bourde dans mon code que je ne sais pas réparer, et sur mon blog s’affiche un pavé de code.
    Help !

  8. Bonjour,
    je bloque complètement depuis quelques heures sur mon menu en haut de page.
    C’est la première fois que j’utilise jQuery donc j’ai sûrement fait une erreur quelque part.
    Pouvez-vous m’aider ?
    Merci 🙂

  9. tu devrais lire l’article que je t’ai mise en lien, il te serait pas mal utile pour faire ce que tu souhaite.. il y a des exemples pour que tu comprennes les possibilités des margin, padding,etc.

    solution magicien :

    il faut que tu comble l’écart entre tes deux menus par une ligne de couleur qui correspond à ton arrière plan.. et on ne verra plus le contenu au travers tes menus.. par exemple avec une div et un padding…

  10. bon, en fait, mon pb c’est que j’ai 2 menus en haut de ma page, ok? et entre les 2 menus il y a un petit espace à travers lequel on peut voir le bckground.
    je veux que le défilement s’arrête juste avant le 2ème menu (celui en bas) . quand je fixe le margin à 0, les deux menus seront collés , alors que moi je désire garder le petit espace
    🙂

  11. Ok… là j’ai compris ! 😀

    En fait tu vois dans l’exemple, il n’y a pas de règles de margin sur pou les autres éléments du coup par défaut une marge est créée pour tout le monde. .. pour qu’il n’y ait plus cette espace/marge il faut que tu rajoute margin: 0 auto; le 0 pour les marges hautes et basses et l’auto pour la gauche et la droite. ..

    si tu veux tu peux regarder l’article : http://www.alsacreations.com/article/lire/629-fusion-des-marges.html

  12. Je ne suis pas sûr d’avoir compris, le menu doit rester au dessus du contenu ? j’avoue ne pas vraiment comprendre.

    .. .essaie de rajouter un z-index : 50 (par exemple) à ton menu, il devrait passer au dessus de ton contenu ..
    Sinon rajoute une marge à ton contenu pour faire la différence de hauteur conteneur/menu.. .

    Vu que je ne suis pas certain d’avoir compris ce que tu demandais je réponds un peu au pif. . Bon courage

  13. bonjour

    merci pour l’article, sauf que j’ai un petit soucis, je souhaite que mon contenu s’arrête juste au dessous de mon menu, c-à-d que lorsque je défile, mon contenu ne passe pas derrière mon menu, ça défile et puis ça disparait, je ne le vois pas passer au dessus du menu.

    j’espère avoir été claire 🙂 🙂

  14. @Loïc

    Je viens de réussir à le faire fonctionner dans un WordPress. Je passe par les mêmes étapes que toi, à savoir :
    – dans header.php, dans le « head» de la page, j’ajoute un appel à la bibliothèque jQuery (1.7.1.min.js pour avoir comme dans la demo) vérification faite, il le faut.
    – toujours dans header.php, la «div id= »#navbar » class= » navbar »» de mon thème devient une «div id= »#navbar » class= » »»
    – dans style.css je crée une #navbar.floatable { avec les instructions qui vont bien}
    -dans footer.php je copie le script juste avant «/body»

    J’avais plantage sur plantage avant de voir que Firebug me renvoyait une synthax error :
    dans le javascript j’avais (recopié)
    if ($(window).scrollTop()
    & g t ;
    = positionElementInPage) {
    alors qu’il faut
    if ($(window).scrollTop() >= positionElementInPage) {
    comme tu peu le voir sur la démo.

    depuis ça marche, j’ai même ajouté une condition pour afficher 28px plus bas pour les admins à cause de la barre (que je masque pour les autres utilisateurs).

  15. J’aimerai utiliser cette fonction pour mon site mais je rencontre des difficultés…

    Je travail sur un WordPress, et il semble que le script ne soit pas prit en compte car le navigateur affiche par default le CSS de menu-float.floatable {position:fixed} et non menu-float {…}.

    voici se que j’ai fait :
    – j’ai modifié le fichier header.php en y appelant dans le head:

    – ensuite dans le fichier footer.php, juste avant le j’appel la fonction :

    // listen for scroll
    var positionElementInPage = $(‘#menu-float’).offset().top;
    $(window).scroll(
    function() {
    if ($(window).scrollTop() >= positionElementInPage) {
    // fixed
    $(‘#menu-float’).addClass(« floatable »);
    } else {
    // relative
    $(‘#menu-float’).removeClass(« floatable »);
    }
    }
    );

    – enfin j’ai défini mes 2 étapes dans le CSS :

    #menu-float{
    margin: 0 auto;
    max-width: 1600px;
    width: 100%;}

    #menu-float.floatable {
    position: fixed;
    top: 0; // non-obligatoire
    }

    Ma question est donc pourquoi le script ne se déclenche pas? y’a t’il une déclaration spécifique pour les wordpress?

    Merci de votre aide !

  16. Bonjour Thomas,

    Pour que ton menu garde la même largeur il faut que tu modifie le css de ta div enfant de ta Div menu. Donner une largeur à la div enfant par exemple, margin : 0 auto.. .

  17. Bonjour,

    Tout d’abord merci pour l’article cependant je rencontre deux problèmes :
    1 : TypeError: jQuery(…).offset(…) is undefined
    Du coup pour pouvoir tester le reste j’ai remplacer la variable  » positionElementInPage « , par une valeur fixe mais j’aimerais tout de même réussir à récupérer la position de ma div à l’aide d’une fonction (ça fait plus propre).
    2 : Le css est modifié.
    Je m’explique, sur le principe ça fonctionne, mais quand je j’appelle  » .addClass(« floatable »); « , cela modifie le design de ma page. En effet, je suis censé avoir un menu qui ne prend pas toute la largeur de ma page, mais dans ce cas, ma barre de menu s’agrandit et prend toute la largeur…

    Si quelqu’un pourrait me donner des conseils/indices pour résoudre mes problèmes, ça serait vraiment sympa.

    En vous remerciant par avance,

  18. Bonjour,
    merci beaucoup pour ce tuto, cependant je rencontre un petit problème. J’utilise le CMS Joomla (1.5), et je suis parvenu à faire fonctionner ce script, mais uniquement sur ma page d’accueil… Si je navigue dans une autre page du site, le menu ne se déplace plus… Auriez-vous une idée ?
    Merci d’avance

  19. Bonjour, j’ai essayé de suivre les étapes mais sans succès. Voici ce que j’ai effectué :

    dans mon .tpl :

    // listen for scroll
    var positionElementInPage = $(‘#content_prices’).offset().top;
    $(window).scroll(
    function() {
    if ($(window).scrollTop() >= positionElementInPage) {
    // fixed
    $(‘#content_prices’).addClass(« floatable »);
    } else {
    // relative
    $(‘#content_prices’).removeClass(« floatable »);
    }
    }
    );

    Source article : https://desgeeksetdeslettres.com/programmation-java/menu-fixe-mais-flottant-selon-la-scrollbar-js-css#ixzz2bIBWLtkv

    et dans mon .css :

    .content_prices {
    /*margin-top:-110px;
    padding-top:10px;
    /*border-top:1px solid #ccc; */
    /*text-align:right;
    width: 125px ;
    float: right;
    margin-left:600px; */
    /*margin-top: 5px; */
    /*padding: 10px; */
    /*position: fixed;*/
    /*border: 1px solid #CCCCCC; */
    float: right;
    text-align: right;
    width: 178px;
    height: 0px;
    /*position: relative;*/
    margin-left: 573px;

    }

    .content_prices.floatable {
    position: fixed;

    }

  20. Super, très bien, exactement ce qu’il me fallait !!
    J’ai mis le paquet de texte dans une div et j’ai un un petit souci de largeur du texte mais cela passe très bien quand même.

    Merci

  21. Bonjour,

    Très bonne ressource, qui fonctionne chez moi.

    Je cherche maintenant à borner le menu une seconde fois en bas (pour ne pas empiéter sur le footer).
    Les modification que j’ai faites fonctionnent mais uniquement sous firefox (et pas sous chrome), et de manière stroboscopique… c’est décoiffant 🙂

    Avez vous déjà réalisé un menu flottant doublement borné ? Si oui je suis preneur d’infos.

    Dans tous les cas je suis à votre disposition pour vous fournir mon code (qui n’a pas de place dans un commentaire à mon sens).

    Bonne journée,
    Etienne

  22. Merci pour ce script très simple à mettre en place surtout pour un débutant comme moi.
    Cependant je rencontre un problème gênant: selon la résolution de l’écran le menue ce déplace.
    Existe il une façon de corriger ce problème, sachant que je suis débutant en CSS.

  23. Merci pour ton aide. Exact, ma page est en mode Quirks et effectivement cela fonctionne avec les bons modes de document. Le soucis c’est que mes pages ont été faites avec frontpage (avec des tableau et du css bidouillé ) et que je n’ai que ça en haut de ma page :
    Pas de doctype…
    En mettant en normes IE9, ça fonctionne mais mon disign de site est alors … ravagé :/
    Bref, je suis un peu coincé …

  24. Chez moi cela fonctionne bien (testé IE9 et IE10), vérifie bien que le « Mode navigateur » soit IE9 et que le « Mode de document » soit aussi en « normes IE9 » ou « normes » tout court.
    Tu appuies sur F12 pour voir apparaître tout ça.

  25. Bon, et bien, j’ai trouvé une petite bidouille.
    J’ai crée un deuxième élément « fantome » qui prend la place du premier quand celui ci sort du flux.

    Au cas où certains auraient le problème, voilà l’idée :
    CSS :
    #infoGhost{
    width:100%;
    display:none;
    }

    JS :
    var fixedLimit = $(‘#info’).offset().top;
    $(‘#infoGhost’).css(‘height’, $(‘#info’).height() + ‘px’);
    $(window).trigger(‘scroll’);

    $(window).scroll(function(event){
    if($(window).scrollTop()>= fixedLimit){
    $(‘#info’).addClass(‘fixed’);
    $(‘#infoGhost’).show();
    }else{
    $(‘#info’).removeClass(‘fixed’);
    $(‘#infoGhost’).hide();
    }
    });

  26. Bonjour,

    Tout d’abord, merci pour ce petit bout de code.
    Petite question tout de fois. Mon élément que je passe en « fixed » n’est pas un élément placé sur le côté de ma page mais bien dans le corps de mon site. Du coup, en le positionnant en fixe et donc en le faisant sortir de mon flux, le scroll se refait automatiquement car la taille verticale de ma page se modifie.
    Et là, j’ai un problème, car lorsque cela se produit, il passe tour à tour dans les deux conditions (à savoir supérieur à la limite, et inférieur ensuite), ce qui ajoute et enlève la classe, et empêche le scroll de ma page. Je ne rencontre pas le problème lorsque la taille de ma page est plus importante mais vu qu’elle est de taille variable, cela peut se produire.

    Je ne sais pas si c’est très clair, et je ne peux pas montrer d’exemple en ligne pour le moment. Mais, quelqu’un aurait une idée pour résoudre ca ?

  27. Bonjour,

    Merci pour le code et le tuto !
    Par contre je n’arrive pas à le faire fonctionner avec wordpress. Une idée pour m’aider ?

    Merci 🙂

  28. Salut, j’adore ce petit code, mais j’ai un petit problème lors de l’implémentation, les navigateurs bloque sur cette erreur « var positionElementInPage = $(‘#menuprincipal’).offset().top; Uncaught TypeError: Cannot read property ‘top’ of undefined » à tu une idée de la solution ?!

    #menuprincipal.floatable {position:fixed;top:0;}

    // listen for scroll
    var positionElementInPage = $(‘#menuprincipal’).offset().top;
    $(window).scroll(
    function() {
    if ($(window).scrollTop() >= positionElementInPage) {
    // fixed
    $(‘#menuprincipal’).addClass(« floatable »);
    } else {
    // relative
    $(‘#menuprincipal’).removeClass(« floatable »);
    }
    }
    );

Laisser un commentaire