Après une demande reçue par e-mail, je me suis dit que la fonctionnalité serait peut-être utile à d’autres que moi.
Lors de la rédaction de ce tutoriel : jQuery – Effet Smooth Scroll (défilement fluide), la complexité du contenu m’a fait retirer une extension intéressante à la dernière fonction/plugin proposée.
Il s’agit d’une mise à jour
- jQuery – Effet smooth scroll (défilement fluide)
- [Mise à jour] jQuery – Effet smoothscroll au chargement de la page
Avant propos
C’est toujours dans une optique de simplicité que j’essaye de présenter mes tutoriels. Il est clair qu’il y a des points parfois difficiles à faire comprendre au plus grand nombre, c’est aussi pour cela que je vous invite toujours à me signaler toute incompréhension sur un tutoriel que vous liriez.
C’est aussi pour cela qu’il m’arrive d’avoir des tutoriels complexes, et de les épurer en retirant des éléments que je juge inutiles – au moins dans un premier temps.
Mise à jour
Le tutoriel « jQuery – Effet Smooth Scroll (défilement fluide) » a été mis à jour aujourd’hui même afin de faire bénéficier à sa troisième partie d’une meilleure prise en charge des URL absolues fournies d’un hash (exemple : http://creativejuiz.fr/blog#kiwi).
Pour les utilisateurs de jQuery 1.9 et supérieures, il faudra penser à remplacer dans le code ci-dessous :
- Live() :
$(this).live('click', function() {
par:
$(this).on('click', function() { - $.Browser :
if ( $.browser.webkit ) container = 'body';
par :
if (navigator.userAgent.match('Chrome')) container = 'body';
Merci à Aurélien pour le code ![]()
Effet de défilement au chargement de la page
Pour effectuer un effet de défilement, voilà comment expliciter la chose en français :
« On cherche à obtenir le même résultat qu’au clic sur l’ancre porteuse du lien vers la cible présente dans la barre d’adresse. »
Il nous faut prendre la phrase à l’envers et la transformer en jQuery.
Donc en plusieurs étapes il nous faut :
- Récupérer le contenu de la barre d’adresse
- Récupérer uniquement le hash
- Chercher dans notre document quel élément pour l’attribut href="#hash"
- Simuler un clic sur cette élément pour déclencher le défilement
Ok, voici un code qui fait ça :
function trigger_click_for_slide() {
var the_hash = document.location.hash;
if(the_hash)
$('a[href~="'+the_hash+'"]').trigger('click');
}
trigger_click_for_slide();La ligne 2 nous permet de stocker directement le hash (fin de l’URL) dans une variable.
La ligne 3 permet de vérifier l’existence d’un hash en bout d’URL.
La ligne 4, primordiale, permet de simuler (trigger) l’évènement click sur l’élément porteur d’un href ciblant le hash trouvé dans l’URL.
Pourquoi imiter le clic sur un lien plutôt que d’effectuer directement une animation ?
Pour éviter de réécrire une portion du code, et aussi pour limiter les animations vers les ancres prévues par notre système de navigation.
Ce morceau de code peut être placé après la création d’une des mini fonctions vues dans l’article jQuery – Effet Smooth Scroll (défilement fluide).
Note : Petite astuce donnée par notre ami Brice pour optimiser cette partie du code. Merci à lui ![]()
Écriture du hash dans l’URL
C’est bien sympa de proposer un défilement au chargement, mais puisque le hash ne s’écrit plus dans la barre d’adresse, comment allez vous faire pour partager une URL fournie d’un hash ?
Il faut le réécrire… oui d’accord, mais comment ?
Si on enlève le return false; en fin de fonction, le défilement va sauter, puis défiler de manière fluide, ou inversement.
Il faut donc le faire une fois l’animation terminée !
Je vous l’avez dit dans le précédent tutoriel à ce sujet, la fonction animate() permet l’accueil d’une fonction de callback.
Nous allons donc créer une fonction au sein du mini plugin vu dans l’ancien article, qui va nous permettre de réécrire le hash dans la barre d’adresse.
La voici :
function write_hash(the_hash) {
document.location.hash = the_hash;
}
Ensuite il faut faire appel à cette fonction dans notre plugin dans la partie qui gère l’animation :
$(container).animate({
scrollTop:$(the_element).offset().top
}, speed, function() {
write_hash(the_hash);
}); Au final, nous avons un code complet qui nous donne :
(function($) {
$.fn.juizScrollTo = function( speed ) {
if ( !speed ) var speed = 'slow';
// coeur du plugin
return this.each( function() {
$(this).live('click', function() {
var goscroll = false;
var the_hash = $(this).attr("href");
var regex = new RegExp("(.*)\#(.*)","gi");
var the_element = '';
if ( the_hash.match("\#(.+)") ) {
the_hash = the_hash.replace(regex,"$2");
if($("#"+the_hash).length>0) {
the_element = "#" + the_hash;
goscroll = true;
}
else if ( $("a[name=" + the_hash + "]").length>0 ) {
the_element = "a[name=" + the_hash + "]";
goscroll = true;
}
if ( goscroll ) {
var container = 'html';
if ( $.browser.webkit ) container = 'body';
$(container).animate( {
scrollTop: $(the_element).offset().top
}, speed, function() {
tab_n_focus(the_hash)
write_hash(the_hash);
});
return false;
}
}
});
});
// fonctions
// écriture du hash
function write_hash( the_hash ) {
document.location.hash = the_hash;
}
// accessibilité au clavier
function tab_n_focus( the_hash ) {
$(the_hash).attr('tabindex','0').focus().removeAttr('tabindex');
}
};
// appel de la fonction sur toutes les ancres !
$('a').juizScrollTo('slow');
// fonction de slide au chargement
function trigger_click_for_slide() {
var the_hash = document.location.hash;
if ( the_hash )
$('a[href~="'+the_hash+'"]').trigger('click');
}
trigger_click_for_slide();
})(jQuery)Avec les versions de jQuery supérieure à 1.7.0, favorisez l’utilisation de on() en lieu et place de live(). Regardez bien la documentation pour effectuer les petits changements adéquats.
Voilà… je crois que nous avons un code plutôt complet pour ce type d’effet :
- Gestion des URLs relatives et absolutes
- Navigation au clavier
- Réécriture du hash dans l’URL (pratique pour le partage d’une info précise)
- Effet smoothscroll au chargement de la page (si on cible quelque chose sur la page via l’URL)
N’hésitez pas à laisser un commentaire pour toute remarque sur ce code, problème rencontré, etc…
Merci pour votre lecture et à la prochaine.



Ça l air plutôt sympa comme effet et ton tuto semble très explicite. Je relirais ton tuto à tete reposé. Àpres 4h de sommeil avec le ptit monstre, les choses se brouilles un peu quand meme …
Ah ah ! Tu nages dans le brouillard ! :p
Merci pour le coup d’œil à venir, je suis ouvert à toute remarque sur le fond comme sur la forme
Bon courage.
Pourquoi ne pas se servir de la propriété location.hash plutôt que des expressions régulières ?
http://www.w3schools.com/jsref/prop_loc_hash.asp
@Birken : merci pour cette remarque.
J’avais le souvenir, peut-être à tort, que IE7 avait un problème d’interprétation de location.hash. Je n’ai donc pas pris la peine de tester, la solution regex me semblait convenir ici.
Je ferai un essai dans le week-end, car ça pourrait davantage simplifier le code
Merci.
Apparement sans problèmes, même avec IE6 :
http://stackoverflow.com/questions/1263509/potential-problems-setting-window-location-hash
Merci pour cette information Birken.
Je corrige mon code en conséquence
Joli tuto, j’avais fait un ptit plugin sur le sujet. Je crois qu’il a un petit souci de compatibilité sur un IE (faudrait que je me repenche dessus).
http://project.cahnory.fr/jquery.scrollIn/
Hey sympa
Merci pour le partage.
Merci pour ce tuto.
Je l’ai adapté pour que le container soit paramétrable pour que l’effet smooth fonctionne aussi dans un div. Du coup, je peux gérer plusieurs scrollbars.
Pour mon cas, j’ai changé le scrollTop en scrollLeft.
En conséquence, mon scrollLeft devient :
scrollLeft: $(the_element).offset().left – $(container).children().offset().left
Je n’ai pas lu le tuto en entier mais si je ne me trompe pas, le résultat final est le même que propose le plugin jQuery « ScrollTo » ?
Bonjour,
Je n’ai pas lu tout ton commentaire mais je pense que tu n’as pas lu tout l’article.
Merci
Après lecture complète :
Ce n’engage que moi mais le plugin jQuery ScrollTo avec éventuellement le plugin jQuery Ascensor, nous permet d’obtenir un résultat plus « propre » que l’exemple de démonstration.
http://www.kirkas.ch/ascensor/
Aucun rapport avec ce tutoriel, mais l’ouverture dans une nouvelle fenêtre pour l’exemple de démonstration permettrait une meilleure navigation pour ne pas dire « experience utilisateur ».
Je te remercie pour ta lecture et ton avis, mais je t’avoue que certaines choses m’échappent :
Concernant ta dernière remarque, on voit là un défaut de maturité de ta réflexion. En quoi imposer un mode de navigation permet de proposer une meilleure expérience utilisateur ? Si l’utilisateur veut ouvrir la démonstration dans un nouvel onglet, il le fait par lui même.
Comment fait l’utilisateur pour ouvrir le lien dans le même onglet si je le force à faire autrement ?
Je suis ouvert à toute explication sur le terme trop vague que tu énonces : « propre ».
Merci et bonne soirée.
- Pourquoi comparer des plugins à un tutoriel ?
Ce n’est pas vraiment le tutoriel en lui même que je compare mais le résultat final (visuel).
- Pourquoi comparer deux outils qui n’ont pas la même vocation ?
Selon le niveau de la personne, elle peut être plus ou moins effrayée par toutes ces lignes de codes et ne cherchera pas à décrypter. C’est pourquoi, j’ai « soumis » deux plugins. Après je suis entièrement d’accord, celui qui souhaite vraiment mettre les mains dans le code, l’améliorer à sa sauce ou comprendre comment ça marche, ce tutoriel est juste parfait.
- Pourquoi charger 4 fichiers JS … pour un effet si simple quand deux suffisent dans le cadre de l’animation que je propose ?
Si l’effet final est exactement celui que propose ton tutoriel, il est clair qu’il vaut mieux utiliser 1 seul fichier JS (ton code). ScrollTo et Elevator proposent pas mal d’options super intéressantes et que l’on peut paramétrer très facilement. Sur un gros projet, bien sur ce n’est pas le bienvenu.
- d’ailleurs si je veux partager uniquement ton portfolio à un ami, je ne peux pas…
Mon but n’est pas que l’on partage uniquement une section du site mais le site entier.
- Chez moi si JS est désactivé, mon système d’ancre fonctionne toujours.
Chez moi aussi
. J’ai juste mis un « return false; » pour qu’il n’y ait uniquement le partage de l’URL sans ancre.
Donc en clair, selon l’objectif et le type du projet de chacun, il peut être bon de connaitre ton code ou bien ces deux plugins (ScrollTo marche très bien sans Elevator, mais pas l’inverse).
Bonne soirée.
Alors merci pour cette présentation, même si elle était déjà faite dans la première partie du tutoriel :
http://www.creativejuiz.fr/blog/tutoriels/jquery-effet-smooth-scroll-defilement-fluide
Au moins elle sera également lisible sur cette page.
J’essaye généralement de ne pas être trop centré sur mes propres codes et présenter des alternatives à mes lecteurs.
Concernant le problème de JS désactivé, je parlais de la page de démonstration de Ascensor. J’avoue ne pas avoir testé chez toi.
Merci pour ton commentaire.
Bonne continuation.
PS: tu as une erreur de logique sur un de tes cercles en canvas sur ton portfolio, relis bien les pourcentages.
Salut Geoffrey,
Merci pour ce petit plugin super léger, contrairement à scrollTo (que je n’ai d’ailleurs pas réussi à faire fonctionner, visiblement parce que je n’ai pas chargé en plus localscroll…)
Soit !
Juste pour te dire que je vais utiliser ton plugin, mais qu’il ne marchait pas non plus
Après avoir regardé de plus près, c’est simplement parce que tu appelles $(‘a’).juizScrollTo(‘slow’); avant que le document ne soit chargé.
J’ai donc englobé les dernières lignes (celles hors de la fonction $.fn.juizScrollTo dans un petit « $(document).ready(function(){ … }); » et tout marche nickel maintenant.
Je pense donc que tu pourrais ajouter ces petites lignes dans ton code afin qu’il marche partout
Bonne journée !
Bonjour Roland,
Effectivement dans la première partie du tutoriel, je fais mention de l’utilisation des scripts en pied de document, ce qui fait que le DOM est censé être prêt à ce moment.
J’ai donc rajouté la petite exception en note, ce qui m’évite de réécrire les autres parties du tutoriel.
Merci pour ton intervention fort apprécié.
Bonne journée à toi, et bonne fête de la musique
Noté
Je t’avoues que je suis en train de développer une grosse application (3 mois de dév prévu) et qu’ainsi je n’ai pas pris le temps de lire tout ton tuto (d’autant que je connais très bien JS etc. donc les bases m’intéressent peu).
Du coup, je n’ai effectivement pas vu que tu préférais utiliser le JS en fin de document plutôt qu’en début.
Bonne fête de la musique à toi aussi !
Génial merci !! super pratique est très simple a intégrer !!
Merci pour ton retour d’implémentation
Bonjour, excellent tuto merci beaucoup ^^
Je me demande, comment pourrais-je faire pour ajouter à ton code de quoi naviguer entre mes ancres via les touches du claviers ?
Je m’y mets, mais je débute dans Jquery ^^
Bonjour Geoffrey,
C’est possible, essaye de regarder du côté du code proposé sur cette page de démo de scroll fluide étape par étape.
Le code a été créé à la suite d’une demande d’un lecteur sur cet article.
L’idée de base était de naviguer de section en section avec uniquement deux boutons. On peut aisément imaginer capturer la pression sur les touches « flèche haut » et « flèche bas » ainsi :
Je te laisse chercher la suite ? :p
Bon courage !
Salut Geoffrey,
Aujourd’hui, je constate que j’ai une erreur JS « Une chaine vide à été transmise à document.getElementById() » dans jquery.js.
Je galère et cherche à isoler le problème… Le problème survient lorsque je clique sur un lien, un lien qui a pour href= »# ».
Je cherche la raison et je retombe sur ton script…
Dedans, ta condition if ( the_hash.match(« \# ») ) { n’est pas bonne. En effet, ça match tout de même lorsque l’ancre est juste « # ». Une chaine vide est conservée dans « the_element » et tu l’envoies à jQuery via $(the_element)…
Bonne correction et à bientôt !
Hello,
Merci pour ton retour.
J’ai apporté une précision sur l’expression, cependant la console de Firebug ne me retourne aucune erreur, même si c’est effectivement une erreur :/
Après il est également possible d’être plus précis dans la « sélection » des éléments sur lesquels on applique ce plugin, c’est vrai que mon exemple cible tous les liens sans exception.
Au plaisir et bonne continuation.
Salut Geoffrey,
Et merci de partager ainsi tes ressources ! Au passage, ton site est vraiment sympa, j’apprécie quand le style graphique permet de renforcer le propos.
Je ne comprend pas grand chose au JavaScript mais je maîtrise assez bien les CSS (et le copier/coller hum !). J’ai donc pu implémenter ton scroll dans une version avec une navigation fixe ici
Mais j’ai un souci : comment gérer la hauteur de la classe .part en fonction de la taille de son contenu et non sur 100% de la hauteur de la page ? Pour l’instant j’ai fixé des min-height mais ce n’est pas le top. En l’occurrence, le volet bottom n’est pas très rempli et il ne scroll pas jusqu’en haut…
C’est grave, docteur ?
Bonjour !
Merci beaucoup
Dans ton cas, comme tu as déjà du
height:100%sur tous les conteneurs parents de .part. Il te suffirait de dire :Mais sinon ce n’est pas trop grâce dans l’absolu, c’est une question d’apparence :p
Bonjour,
Depuis jQuery 1.9, la propriété « browser » a été supprimée (elle était dépréciée avant).
Comment peut-on remplacer la condition sur le browser dans votre code ?
Merci pour ce code clair et précis.
Bonjour Tristan,
Merci pour l’info, je ne l’avais pas vu passer.
Le problème c’est qu’ici il n’y a pas moyen de remplacer $.browser par $.support comme le suggère la documentation, puisqu’il s’agit bien d’une spécificité de webkit.
Du coup on est obligé de coder moins précisément et de remplacer :
par
Du coup on duplique l’animation dans les deux conteneurs, ce que je souhaitais éviter, m’enfin tant pis.
Encore merci
Oui, c’est ce que j’ai fait. :/
Quels sont les possibles désagréments causés par l’application sur les 2 éléments ?
On pourrait se tourner vers un plugin de détection de navigateur indépendant, mais ça me paraît être une solution un peu « lourde ».
http://www.quirksmode.org/js/detect.html
Je ne suis pas très technicien à ce niveau, mais si je ne m’abuse en demande inutilement au CPU de calculer une animation qui s’applique deux fois à des éléments différents. Autant économiser son utilisation dès qu’on le peut.
Bonjour,
Je viens de lire votre tuto et le mettre en place.
J’ai eu des problèmes a cause du support de jquery 1.9.
J’ai trouvé cet article qui donne un lien vers le js jquery.browser.min.js
http://chez-syl.fr/2013/02/jquery-1-9-et-browser/
Je l’ai mis en place et ça fonctionne supper.
Merci a toi Geoffrey pour tes tutos
Hello,
J’allais justement publier un script équivalent, mais c’est nickel s’il existe déjà.
Parfait merci
Bonsoir,
Merci beaucoup pour ce tutoriel clair et détaillé
Pour mettre à jour le script en jQuery 1.9.x, j’utilise la solution suivante:
1. Remplacer Live() :
$(this).live(‘click’, function() {
par:
$(this).on(‘click’, function() {
2. Remplacer $.Browser :
if ( $.browser.webkit ) container = ‘body’;
par :
if (navigator.userAgent.match(« Chrome »)) container = ‘body’;
Si quelqu’un a encore mieux, je suis preneur!
Bonjour Aurélien,
Oui il faudrait que je mette à jour le script, cependant j’ai un parti pris assez important concernant jQuery 1.9. En production, dès que je peux utiliser une version antérieure de jQuery je le fais, pour des raisons de poids de la librairie notamment. Il m’arrive même souvent d’utiliser plutôt jQuip tellement jQuery est trop fourni à la base. J’avoue cependant ne pas avoir zieuté jQuery 1.9.
En tout cas j’ajoute ton code qui me semble largement suffisant pour contourner les problèmes de compatibilité. Merci.
Bonjour,
Merci pour ton commentaire
Je me permets de réagir sur l’utilisation de jQuip, il semblerait que son utilisation ne soit plus légitime.
Voir l’article assez intéressant :
http://www.mathieurobin.com/2011/11/jquip-cie-une-fausse-bonne-idee/
Bonjour,
Tout d’abord bravo pour votre site rempli d’articles intéressants.
Concernant ce plugin, je l’utilise pour remplacer le lourd « ScrollTo » et « localScroll ».
Par contre, je n’arrive pas à faire fonctionner l’animation au chargement de la page. Ne serait ce pas du au fait que si l’url contient un hash (#monancre) le navigateur amène l’utilisateur directement à cette ancre avant même que l’animation ait pu s’exécuter ? Du coup il n’y a pas d’animation puisque l’on se trouve déjà au bon endroit.
Ne faudrait il pas annuler le comportement par défaut du navigateur concernant les ancres ?
Merci d’avance pour votre aide.
Hello,
Effectivement dans l’absolu il faudrait court-circuiter le comportement par défaut du navigateur, mais testé sous Chrome et Firefox, cela semble plutôt bien tourner.
Il s’agit bien d’un scroll auto au chargement de la page, pas au changement manuel de l’URL.
Tu as quel comportement sur ma démo ?
Il est vrai que je n’ai pas ce comportement non plus sur mon site, même si sur la démo ça fonctionne.
Mais bon, ça me paraît accessoire.
Hum non chez moi quand j’ai testé je n’avais aucune animation et je me retrouvais directement à l’ancre.
J’ai réussi à faire l’animation au chargement de la page et au changement manuel de l’url en mettant ce bout de code :
Ok ça roule, merci pour ton astuce.
Je rajouter l’info à l’article