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
⇒ Changez votre adresse IP et accédez aux contenus bloqués ou géo-restreints partout dans le monde
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.
Merci Mimie, il n’y a plus besoin de publier mon précédent post, j’ai résolu mon problème. J’ai retourné le problème 20 fois et j’avais oublié un règle css…. Frôler le suicide nerveux fait partie des risques du métier n’est-ce pas… Merci encore pour ton script!
Bonjour et merci pour ce tuto qui marche à merveille.
J’aimerais cependant pousser la chose avec 2 menus flottant qui passeraient en fixe l’un après l’autre.
Par exemple, si l’on prend ton fichier source Mimi, on pourrait imaginer un deuxième texte fixe, plus bas. Quand le scroller arriverait à sa hauteur, le premier texte fixe céderait sa place au second.
Je suis donc parti sur ce code (qui parait tout simple en théorie) :
var positionElementInPage1 = $(‘#category1’).offset().top;
var positionElementInPage2 = $(‘#category2’).offset().top;
$(window).scroll(
function() {
if ($(window).scrollTop() >= positionElementInPage1 && $(window).scrollTop() positionElementInPage1 && $(window).scrollTop() >= positionElementInPage2) {
// fixed
$(‘#category1’).removeClass(« floatable »);
$(‘#category2’).addClass(« floatable »);
}
if ($(window).scrollTop() < positionElementInPage1){
// relative
$('#category1').removeClass("floatable");
$('#category2').removeClass("floatable");
}
}
);
Mais voilà ça ne fonctionne pas. Le premier item réagit parfaitement mais arrivé à la hauteur du second, les 2 sont masqués par le scroller. Pourtant l'inspecteur d'élément me confirme bien que la class "floatable" passe bien de l'un à l'autre… Aurais-je oublié quelque chose? Merci infiniment.
j’ai mis ça : if ($(window).scrollTop() >190) {
au lieu de : if ($(window).scrollTop() >= positionElementInPage) {
ça à l’air de marché! je ne suis pas sur que cela soit la bonne solution!
solution pour l’alignement comme en relative :
width:100%;
position:absolute;
j’ai toujours la barre de menu qui se fixe d’un coup tout en haut ;+. j’y retourne
J’ai mis le code javascript en haut, en pensant que ce la n’influencerait pas l’action et ben si ! dans quel cas il faut mettre le code après la div concernée ?
J’ai mis le code en bas dans ma page de site.. .quelque chose se passe.. Lorsque je scroll vers le bas la barre de menu ce colle tout de suite en haut de la fenêtre.. le css de la div :
#breadscrumbs {background-color: rgba(56, 50, 58, 0.8); height:30px; z-index:5; position: relative;}
j’ai surement de la bidouille à faire. est ce qu’il y a une solution pour que la barre reste comme en position relative, c’est-a-dire, avec un background-color infini, là en position fixed, la largeur est de 960px (mon site) et aligné sur la gauche de l’écran ?
je viens de faire un copié coller de l’example.. .ça ne marche pas! je ne pige pas là! je vais chercher mais si tu as une idée qui te viendrais n’hésite pas. Merci d’avance.
J’ai bien regardé l’exemple, je dois avoir un conflit quelque part, je n’arrive pas à savoir où ? pourquoi ? comment ? Je vais taché de refaire l’exemple pour vérifier que je n’ai pas fait d’erreur d’inattention. des fois quand je teste un code Jquery il ne marche pas du premier coup, je n’y touche pas et le navigateur le prend bien en compte.. peu que c’est ça.
@benjamin: Il y a pourtant un paragraphe « Sources » avec un exemple en ligne, je ne peux pas faire grand chose de plus …
Bonjour,
je croise les doigts pour que le post marche encore.. . 😀
J’ai mis le même code … mais ça ne marche pas. J’ai bien installé j.query (moi c’est la version :jquery-1.8.3.js). j’ai fait les manipes dictées plus haut sans résultats.. .
Je veux bien un coup de main. .
MEEEEERRRRCIIIIIIII !!!!!!!
Ca faisait des semaines que je recherchais un script de ce genre, et il FONCTIONNE !!!! (en tout cas chez moi 🙂 )
Merci, merci, merci et encore merci !!!!!!!!!!!!!!!
Merci pour l’article qui m’a bien servi aujourd’hui 🙂
Bonjour,
J’aimerais bien l’utiliser mais je n’ai pas de fichier menu.js.
J’ai un menu nav.menu.js dans mon wordpress , c’est tout 🙁
Des idées?
c super! ca ma vraiment aide… merci encore une fois!
ça c’est une façon d’expliquer
Vivedidi, dans l’exemple donné on teste si la scroll masque le menu pour le faire descendre, il faut dans ton cas (qui est aussi le mien sur magicsupremacy) que tu rajoutes la même chose pour ton footer et tester quand la scroll arrive au niveau de ton footer pour ne pas le masquer, quelque chose du genre :
Bonjour,
merci beaucoup pour ce post fort utile ! Cependant je suis dans le même cas que Vivedidi, je voudrais que le position fixed que j’ai ne chevauche pas mon footer. Il faudrait donc rajouter une troisième classe (relative 2) avec en css un vertical-align bottom, jusque là ça va. Mais n’étant pas familier du javascript ou du jquery, je n’arrive pas à bidouiller une condition pour déterminer si l’élément est rendu au footer ou non …
Un peu d’aide serait la bienvenue
Merci !
Bonjour, je remonte un vieil article, j’espère avoir une réponse quand même ^^
J’ai suivi cet article, fait l’installation, fonctionne correctement, sauf que mon menu ne s’arrête pas à la fin du div contenant mon menu (le menu est dans le footer ensuite).
Je n’ai pas fais de Jquery, mais j’ai quand même tenté des truc en utilisant la position du pied de page, du scroll, ou du bas du menu, mais je n’ai pas encore trouvé.
Donc si quelqu’un pouvait m’apporter son aide, peut-être est-ce dû au code css.
j’ai bidouillé un truc, mais il doit y avoir tellement plus simple
(voir: http://carrecarre.com/newindex2.php)
Les seuls petits defaults que je trouve à redire sont
Le petit espace qui se cree au top de la balise p qui se regle en la remplacant par une div par exemple.
Et ce petit saut (de la taille de la fenetre (encore elle)) lorsqu’elle se transforme en floatable et qui recouvre les trois premiére ligne du texte en dessous
J’essaye de regler sur ma page test http://carrecarre.com/newindex2.php encore 5 minutes et je vais prendre une coupe de champagne.
merci pour l’aide et l’article.
Merci beaucoup ! C’est très clair !
Voilà, section « sources » en bas de l’article.
et bien je pense que nous attendons ca avec impatience.
merci du temps accordé
D’accord, je vais essayer de vous faire ça dans la journée, je vous tiens au courant.
je suis preneur aussi, j’aimerais bien arriver à le faire.
Bonjour,
Pourriez-vous créer un fichier d’exemple simple téléchargeable ? votre menu semble en effet très intéressant mais l’explication n’est peut-être pas très claire pour un « amateur » (comme moi).
Merci !
Merci !
Bonne continuation à vous !
Une bonne chose de faite, bonne continuation.
Je me suis creusé la tête longtemps… longtemps…
J’avais mal paramétré mon fichier css du coup il croyait que mon menu commencer tout en haut de la page. J’ai décalé mon menu et tout est rentré dans l’ordre !
$ est une fonction jQuery, il semblerait donc que tu pointes sur un fichier jQuery non disponible, le navigateur n’arrive pas à télécharger la bibliothèque jQuery, creuse de ce côté là peut-être.
$ is not defined
menu2.js()menu2.js (ligne 1)
[Stopper sur une erreur] var positionElementInPage = $(‘#menu’).offset().top;
Voila ce que ça me donne sous firebug. Elle est peut être là l’erreur mais je la comprend pas.
Non ce n’est pas pareil :
– « #menu .ok » signifie l’élément dont la classe est « ok » et dont un de ses éléments parent possède un identifiant « menu »
– « #menu.ok » signifie l’élément dont l’identifiant est « menu » et dont la classe est « ok »
Essaie de débugger avec Firebug sous Firefox, tu dois avoir une erreur quelque part.
Pour le point numéro 1, j’ai essayé mais ça ne change rien (et je pense que c’est pareil en css), et pour le point numéro 2 … c’est pareil !!
Ça m’embête mon histoire !
@Valentin : 2 pistes pour ton problème :
1/ dans ton css tu as mis « #menu .ok » au lieu de « #menu.ok » (aucun espace)
2/ essaie ensuite de charger le fichier menu.js en bas de page, juste avant le </body>
Envoyé !
Etrange, envoie-moi un zip avec ton code si tu veux, je prendrai le temps de regarder ce que tu fais.
Merci beaucoup, effectivement je l’avais oublié.
Mais ça n’a absolument rien changé, je ne comprends pas !
Bonjour Valentin, déjà il faut que tu saches si tu inclus bien la bibliothèque jQuery, si ce n’est pas le cas voici la ligne à rajouter dans ton head :
<script type= »text/javascript » src= »http://code.jquery.com/jquery-1.5.2.min.js »></script>
Retente avec ça on sait jamais.
Bonjour,
Je souhaite utiliser ce code pour mon site mais je suis incapable de le mettre en pratique.
Je n’ai pas de connaissance en javascript car je n’ai pas le temps d’apprendre pour le moment.
Ce que je fais :
– Dans mon css, j’ai deux fois mon menu (un avec « #menu » et l’autre « #menu.floatable »),
– Dans mon html j’ai une balise
– Et dans menu.js j’ai ce que vous avez écrit (var …blablabla )
Mais voilà, ça marche pas !
La raison est sûrement évidente mais je ne la vois pas.
Merci pour votre aide !
C’est pile ce que je recherchais,
infiniment : Merci 😉
+1, tous les détails comptent 😀
Sympa l’effet en pratique, en effet 🙂