Un défilement animé (« Smooth scroll ») en jQuery sans plugin
Nous avons vu précédemment comment réaliser un site de type « one-page » en full CSS. On va maintenant égayer la navigation entre les rubriques en y ajoutant un effet de défilement animé (« smooth scroll ») en jQuery.
Cet effet sera déclenché au clic sur un élément ayant une classe js-scrollTo
(cela permet de ne pas limiter son application au menu et de faire fonctionner le défilement également sur des liens internes). Le préfixe js-
permet de différencier les classes à vocations cosmétiques de celles dédiées à l’interactivité JS.
Exemple avec les liens du menu :
<ul class="menu">
<li><a class="js-scrollTo" href="#page-1">Page 1</a></li>
<li><a class="js-scrollTo" href="#page-2">Page 2</a></li>
</ul>
<div id="page-1">
<!-- Contenu Page 1 -->
</div><!-- /page-1 -->
<div id="page-2">
<!-- Contenu Page 2 -->
</div><!-- /page-2 -->
Le code javascript (à placer dans <head>
ou juste avant </body>
) permettant de réaliser le défilement :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('.js-scrollTo').on('click', function() { // Au clic sur un élément
var page = $(this).attr('href'); // Page cible
var speed = 750; // Durée de l'animation (en ms)
$('html, body').animate( { scrollTop: $(page).offset().top }, speed ); // Go
return false;
});
});
</script>
La méthode .offset()
renvoie les coordonnées (relatives au document) de l’élément (ici la page ciblée). On modifie la position de la scrollbar (grâce à scrollTop
) jusqu’à atteindre cet élément, en animant le défilement avec .animate()
.
Commentaires (72)
Lâcher un com'
Merci pour ce tutoriel clair et concis, je pensais que c’était beaucoup plus complexe à réaliser. Ça a marché du premier coup, je suis super content !
Très simple, merci !
Super simple et facile à intégrer, Merci !
Efficace, merci !
Super simple, merci beaucoup !!
bonsoir, une petite question, lorsque j’utilise le plugin, qui fonctionne très bien, mon slider (qui utilise lui aussi du Jquery) ne fonctionne plus, idée?
@minimoi :
Bonjour, pas de raison que ce bout de code empêche votre slider de fonctionner, sauf si :
Vous appelez 2 versions différentes de jQuery qui entrent en conflit
=> Vérifiez les appels de la librairie dans votre source
Votre slider utilise également une classe « scrollTo »
=> Changez le nom de la classe utilisé pour le smooth scroll
Mais sans voir la page qui pose problème, difficile d’en dire plus…
Bonsoir,
Y aurait-il une solution pour faire fonctionner le script pour un défilement à l’horizontal ?
@Max :
Bonjour,
En utilisant les méthodes jQuery relatives à la position et aux coordonnées horizontales (plutôt que verticales), cela devrait fonctionner.
Donc, à la place de :
scrollTop: $(page).offset().top
Essayer :
scrollLeft: $(page).offset().left
Merci beaucoup ! Ça fonctionne parfaitement.
Vraiment simple d’utilisation, merci pour ce tuto !
Salut! simpléfficace … merci beaucoup :-)
merci ;) simple et efficace !
Bonjour,
J’essaye ce code là pour ma web app sur ipad mais…ça marche pas :(
Bonjour bonjour !
Tout d’abord merci pour ce morceau de code qui marche du premier coup !
Mais il ne marche pas sur IE, une idée d’un bout de code pour le fix ?
Bonjour,
@Myhia :
Pas de raison que le script ne fonctionne pas sur ta web app, le problème vient donc d’autre chose.
@Simon :
Le script devrait fonctionner sans souci sur IE, la preuve avec la démo. Le problème est ailleurs !
Super script merci, est-ce qu’il y a moyen de laisser un offset une fois arrivé à destination? J’ai une barre de navigation fixe et quand ça scroll mon titre arrive derrière ma barre.
Merci :D
@Alex :
Hello, il est préférable d’effectuer ce type d’ajustement en CSS plutôt qu’en JS. Tu peux par exemple ajouter du « padding-top » à ton titre, pour dégager un peu d’espace et éviter le chevauchement des deux éléments.
Simple et efficace ! ;-)
Merci beaucoup !
Code optimisé :) :
$('.scrollTo').click( function(event) {
event.preventDefault();
event.stopPropagation();
var url = $(this).attr('href');
var hash = url.substring(url.indexOf('#'));
$('html, body').animate( { scrollTop: $(hash).offset().top }, 750 );
});
Bonjour Antoine et merci pour ta participation. :)
event.preventDefault();
event.stopPropagation();
Je pense que cela revient plus au moins au même que d’utiliser
return false
(check this). A la limite si l’on souhaite arrêter l’animation avant d’en lancer une autre je pencherais plutôt pourstop().animate()
.var hash = url.substring(url.indexOf('#'));
Dans ton exemple (et avec mon DOM),
hash
contient la même chose queurl
, alors je n’ai pas compris. :)Pour affiner l’effet de passage d’une ancre à une autre en donnant un effet de scroll plus fluide ou plus personnalisé :
var speed = 750;
var easing = 'easeInQuad'; // https://jqueryui.com/easing
$('html, body').animate( { scrollTop: $(page).offset().top }, speed, easing );
N’oubliez pas d’appeler jQuery UI évidemment pour que cela fonctionne correctement.
thanks :D
Merci c’est génial de trouver un tuto aussi efficace !
Bonjour et merci beaucoup :) Extrêmement simple d’utilisation !
Malheureusement j’ai le même soucis que « monimoi » en début de commentaires.
> Dès que j’insère le script, mon menu responsive ne s’affiche plus, et mon bouton pour remonter au dessus de la page quand on est en bas non plus. Quand j’enlève le script, cela refonctionne.
Comme vous l’avez conseillé, j’ai changé le nom de la classe « ScrollTo » mais ce n’est pas ça. Je ne vois donc que la version jQuery qui ne doit pas être la bonne.
Existe t-il un moyen simple de savoir quelle version mettre, ou bien comment trouver la version utilisée de base sur mon site (thème wordpress) ?
merci beaucoup :)
Bonjour Antoine,
Il ne s’agit pas de mettre une autre version de jQuery, mais simplement de ne pas en charger 2 différentes.
Tu peux garder celle utilisée par ton thème wordpress, il suffit juste de ne pas appeler celle indiquée dans le script. La ligne suivante est donc à supprimer :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
Merci pour ce script ! Y’a t’il moyen de modifier l’offset ? J’aimerais ajouter une marge à l’ancre (j’ai un menu fixe en haut de ma page et une partie des divs appelées est cachée)
Qqchose comme { scrollTop: jQuery(page).offset().top -50 } ?
Bonjour Vincent,
Oui pas de souci cela doit fonctionner comme tu l’as écrit.
Une autre solution pour éviter de manipuler dans le JS des données spécifiques à ton design serait d’utiliser des éléments cachés dédiés à l’ancrage :
<div class="page">
<div id="page-1" class="page-ancre"></div>
<!-- Contenu Page 1 -->
</div>
.page { position:relative; }
.page-ancre { position:absolute; top:-50px; left:0; }
Salutations et merci pour le code. Fonctionnel et concis !
Encore merci :)
Bonjour,
Merci pour ce tuto, très clair.
Par contre, lorsque je suis sur ma page contact.php et que je veux revenir sur une ancre de la page index.html. Il ne prend pas en compte l’offset. Il y aurait-il une solution ?
Cordialement, Marti
Bonjour Marti,
Difficile de proposer une solution sans voir le problème. Toutefois :
- Les ancres n’ont rien à voir avec le JS, ça devrait marcher même sans le script. Donc es-tu sûr que le lien de la page contact vers l’ancre de la page index est bon ?
- Ce n’est pas le même problème qu’ici par hasard ?
@BeliG Merci, oui tu as raison ça ressemble à ce souci. Je vais regarder ça en utilisant des éléments cachés pour l’ancrage.
La prochaine fois, je lirais avant de poser une question ! ;)
Encore merci et je crois que je viendrai plus souvent sur ton site car tes tutos sont clairs !
Merci INFINIMENT !!!!! Je cherchais laborieusement un moyen simple de produire cet effet sans passer par des codes jquery monstrueux a implémenter et surtout à adapter car je ne suis pas un pro de ce language :) Avec vos explication j’ai tout capté :D !!!! Merci donc encore et bonne continuation.
Simple, efficace, léger… Bref tout ce que j’aime !
Merci pour cette astuce.
Hey super,
10mn même pas pour un super résultat, le plus long étant sans doute à définir la bonne vitesse de défilement :)
Intégration du 1er coup, ta page est de loin la plus claire que j’ai trouvée avec un script qui s’adapte rapidement
Un grand MERCI, et bonne année ;)
Super enfin un tuto ultra simple et efficace !
C’est exactement ce que je cherchais depuis quelque temps mais chaque fois c’était soit en anglais, soit trop lourd et complexe à mettre en place.
Un grand merci et toute ma reconnaissance éternelle :)
Merci beaucoup !
Simple et efficace !
Super tuto, simple et efficace ! Merci !
Je me posais juste une question : peut-on se passer des « par un simple scroll ». Je m’explique : je passe de la page une à la page deux uniquement en scrollant légèrement vers le bas; puis de la page 2 à la page une uniquement en scrollant légèrement vers le haut ?
Encore MERCI,
D.
Salut Dave,
Pour réaliser ton effet, l’idée serait de détecter la direction du scroll et d’adapter le script de cet article pour faire défiler vers la page +1 ou -1 (par exemple en manipulant une variable basée sur la page courante).
Bon courage. :)
Merci pour ta réponse BeliG !
Bonne continuation et MERCI de nouveau !
D.
C’est parfait, merci beaucoup pour le script !
Super code ! Très simple à utiliser, c’est exactement ce que je cherchais. Merci !!
Rien de plus simple !
Merci beaucoup !
Salut,
le code fonctionne super bien, par contre l’ancre dans mon url ne s’affiche pas et ma div de destination et en display:none à la base et s’affiche avec un :target
Comment je peux faire pour que l’ancre quand je clique sur mon lien s’affiche dans l’url ?
Merci d’avance.
Hello,
Il y a des solutions en JS / HTML5 pour mettre à jour l’URL sans recharger la page (#1 / #2), mais ça me semble lourd (et pas adapté) à ce que tu cherches à faire.
Le plus simple est de revoir la méthode d’affichage de tes sections. Tu as l’id dans la variable
page
, pourquoi ne pas tout simplement$(page).show()
?merci pour ce petit script
Grand merci ! c’est très simple et efficace
Merci beaucoup, j’aime les choses simples avec js ;)
Bonjour, j’ai un petit soucis.
Je suis sur un thème wordpress et le défilement ne fonctionne pas. Quand je clic sur mon menu, j’atterris bien sur la section voulu mais pas de fluidité du tout.
Comment je peux faire ?
Merci
Bonjour Justine,
Si on parle de ton blog, je remarque que jQuery est déjà appelé, tu ne dois donc pas ajouter la ligne :
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
Je vois aussi que chez toi les déclarations jQuery sont « protégées ». Essaye de remplacer :
$(document).ready(function() {
par :
jQuery(document).ready(function($) {
Ah heureusement que j’ai rencontré cet article
NIKEL
un GRAND MERCI. Simple et efficace.
Très rapide et terriblement efficace, merci !
Bonjour j’ai un petit problème :
le code marche très bien pour aller d’une partie de la page à une autre, mais l’effet ne fonctionne pas quand ma balise « a » mène vers href= »# » :/
merci pour votre aide ;)
Bonjour,
Je ne suis pas sûr de comprendre votre problème. C’est l’effet de défilement qui ne fonctionne pas ?
Vous ne pouvez pas faire défiler vers « # », il faut forcément indiquer l’id d’un élément dans votre page.
Si vous souhaitez animer un retour vers le haut de la page il vous faut un
<div id="header">
et un<a class="js-scrollTo" href="#header">Top</a>
Bonjour,
Merci pour ce tuto!
J’aurais voulu savoir comment faire pour qu’il y ait un décalage entre le haut de la page et l’ancre en elle-même, car dans mon cas, une partie de mon texte se retrouve caché derrière le bandeau de mon menu.
Merci d’avance.
Bonjour Arnault,
Il y a 3 solutions simples pour régler ton problème :
=> Aérer chacune de tes pages (éléments avec ancres) avec un
padding-top
correspondant à la hauteur de ton menu.=> Ajouter dans le JS une valeur permettant de modifier l’offset.
=> Utiliser un élément dédié à l’ancrage positionné en absolute.
Pour les deux derniers points tu peux jeter un coup d’oeil à ce commentaire.
Bonjour,
J’ai le même problème que Phen’X:
Le passage d’une partie à une autre fonctionne, mais pas l’effet de défilement :/
Bonjour cherELF,
Si l’effet de défilement ne fonctionne pas, c’est qu’il y a un problème avec le JS. Que dit la console (au chargement de la page et lors du clic sur un lien du menu) ?
Très clair, merci
Bonjour,
super tuto, merci!
Y a-t-il un moyen de faire un smooth scroll à l’ouverture d’une autre page à laquelle on accède par un lien?
Je m’explique j’ai un menu avec plusieurs liens donnant sur d’autres pages. J’aimerai que quand on clique sur un lien, il y ait un smooth scroll amenant directement à la partie en dessous de ce menu qui est sur toutes mes pages en question.
Bonjour Audrey,
Faire un smooth scroll à l’ouverture d’une page n’est pas quelque chose que les utilisateurs apprécient en général. Le temps que la page et le script se chargent, ils auront sans doute déjà commencé leur navigation. Leur imposer à ce moment un défilement qu’ils n’ont pas demandé n’est pas naturel (et donc désagréable).
Il vaut mieux les amener directement au contenu souhaité grâce à un système d’ancrage classique.
Bonjour,
Merci beaucoup pour ce tuto ! Simple à mettre en place et hyper pratique ! Je suis super contente, je pense y avoir gagné quelques heures ;)
Merci beaucoup pour ce tuto efficace.
Bonjour, j’ai un problème concernant l’animation
Je fait une vue en javascript à partir d’un fichier json
le problème vient du faite que lorsque je génère mon html en js (en string avec un for puis innerHTML pour les ajouté), les liens ne s’anime contrairement au lien déjà dans le html.
j’ai par exemple un navbar qui possède les lien ProposalOverview (dans le html) qui s’anime, mais celui ayant tout les « Proposal » un à un ne s’affiche pas
merci d’avance si vous avez une solution
Bonjour vinte,
Le code, tel qu’il est écrit dans cet article, attache l’évènement
click
aux éléments$('.js-scrollTo')
au chargement de la page.Comme tes liens sont générés dynamiquement, ils ne sont donc pas présents au moment de l’initialisation.
Pour y remédier, il suffit d’attacher l’évènement au document plutôt qu’aux éléments. Essaye de remplacer :
$('.js-scrollTo').on('click', function() {
Par :
$(document).on('click', '.js-scrollTo', function() {
Bonjour
Magnifique, c’est ce que je cherche depuis des mois mais (j’ai mis le script en place mais je ne sais pas quoi faire ensuite et plus particulièrement (à mon avis) il doit y avoir un tag/code à mettre dans la homepage et dans le script mais quoi et oû ?
Je dois découper ma homepage en 4 ou 5 parties et le système proposé ici est fantastique. Le problème c’est que les non habitués ne savent pas quoi faire …
Bonjour Gunter,
Si tu as un WordPress et que tu es novice en développement web, ça va être un peu compliqué malheureusement…
La partie délicate consiste à ajouter un script jQuery à WordPress. Disons-le clairement, les tutos que l’on trouve en ligne en français sont tout pourris. Un jour, peut-être, j’en rédigerai un. En attendant, si tu es (très) motivé, voici un fil de discussion qui pourrait t’aider (c’est le plus simple que j’ai trouvé après 30min de recherche).
Ensuite, une fois que tu auras découpé ton contenu en plusieurs parties et que tu auras « englobé » chaque partie dans une
div
avec unid
spécifique :<div id="home-1">Partie 1</div>
<div id="home-2">Partie 2</div>
etc.
Il faudra ajouter la classe CSS
class="js-scrollTo"
à chaque liena
de ton menu en précisant la ciblehref="#home-N"
.Si ton sous-menu est dans le corps de la page (dans
wp-content/themes/TONTHEME/index.php
ou dans une page WP), ça devrait aller.S’il est généré automatiquement via un plugin ou autre, c’est la m*rde.
Bonjour
J’ai installé le script, pas de problème à ce niveau. Tu me dis d’inclure les blocs de la homepage dans des DIV – pas de problème mais … TD Composer (Tagdiv) me donne la homepage sans le header et footer cela devrait être simple dans le composeur. Toutefois voici à quoi ressemble la HP en code …
[tdc_zone type="tdc_content"][vc_row]
[vc_column width="1/1"][vc_empty_space]
[td_block_big_grid_1 sort="random_posts" category_id=""]
[/vc_column][/vc_row][vc_row][vc_column width="1/2"]
[...]
Je ne connais pas tagDiv.
Et leur documentation est inaccessible sans compte. 👍
Le code que tu montres correspond à ce qui est généré à partir des réglages du thème, et ce n’est clairement pas fait pour être modifié comme de l’HTML/CSS classique.
Comme ils ont mis en place un code propriétaire, tu ferais mieux de te rapprocher de leur support pour obtenir de l’aide.
Vos contributions sont très constructif
Laisser un commentaire