Comment faire défiler la page HTML jusqu'à l'ancre donnée?


264

Je voudrais que le navigateur fasse défiler la page jusqu'à une ancre donnée, simplement en utilisant JavaScript.

J'ai spécifié un nameou un idattribut dans mon code HTML:

 <a name="anchorName">..</a>

ou

 <h1 id="anchorName2">..</h1>

J'aimerais obtenir le même effet que vous obtiendriez en naviguant vers http://server.com/path#anchorName. La page doit être défilée de sorte que l'ancre se trouve près du haut de la partie visible de la page.

Réponses:


349
function scrollTo(hash) {
    location.hash = "#" + hash;
}

Aucune jQuery requise du tout!


92
Mais ça ne défile pas, ça saute juste. À ce stade, vous pourriez tout aussi bien créer un lien vers l'ancre<a href="#anchorName">link</a>
Ryan

52
Notez que cela ne fonctionnera qu'une seule fois. Une fois le hachage défini, la page ne défilera pas jusqu'au même hachage à moins que vous ne le changiez en un faux puis le redéfinissez.
Cristian Vrabie

13
Vous ne devez pas utiliser scrollTo, car il est déjà utilisé par l'objet de fenêtre globale. De plus, le paramètre ne doit pas être nommé hachage, car location.hash est également défini. Vous pouvez utiliser ce code:function scrollToHash(hashName) { location.hash = "#" + hashName; }
Markus Zeller

3
@MarkusZeller, pourquoi le paramètre ne devrait-il pas être appelé hachage? Il n'entre pas en collision avec l'emplacement, n'est-ce pas?
Gherman

3
cela défile si vous définissez "scroll-behavior: smooth;" sur l'élément html
stackers

225

Bien plus simple:

var element_to_scroll_to = document.getElementById('anchorName2');
// Or:
var element_to_scroll_to = document.querySelectorAll('.my-element-class')[0];
// Or:
var element_to_scroll_to = $('.my-element-class')[0];
// Basically `element_to_scroll_to` just have to be a reference
// to any DOM element present on the page
// Then:
element_to_scroll_to.scrollIntoView();

22
J'ai d'abord pensé que Mandx était à la traîne, puis j'ai essayé et cela a fonctionné. Au-delà de moi, je n'ai jamais rencontré cette méthode auparavant. Mozilla Docs pour cette méthode . De plus, il semble que cela sera très bien pris en charge dans les navigateurs.
Jonathan Dumaine

2
J'ai eu beaucoup de problèmes avec les solutions jquery qui ne défilent pas. Cela m'a évité beaucoup de frustration.
NuclearPeon

1
AVERTISSEMENT! Cette méthode peut avoir des problèmes si une div au-dessus contient des éléments flottants et ne peut pas déterminer facilement sa taille.
vogomatix du

5
C'est une solution propre, mais pour l'instant, elle ne permet aucun ajustement, elle fait un défilement difficile. Il existe un paramètre expérimental scrollIntoViewOptionsqui a une behavior: "smooth"option, mais il n'est actuellement compatible qu'avec Firefox.
rocha

Comment animer ça?
SkuraZZ

124

Vous pouvez utiliser jQuerys .animate () , .offset () et scrollTop. Comme

$(document.body).animate({
    'scrollTop':   $('#anchorName2').offset().top
}, 2000);

exemple de lien: http://jsbin.com/unasi3/edit

Si vous ne voulez pas animer, utilisez .scrollTop () comme

$(document.body).scrollTop($('#anchorName2').offset().top);

ou javascripts natifs location.hashcomme

location.hash = '#' + anchorid;

1
En ce qui concerne la création d'un sélecteur pour trouver le <h1 id="anchorName">ou un <a name="anchorName">, utilisez $('#'+hash+',a[name='+hash+']')ou légèrement optimisé $(document.getElementById(hash) || 'a[name='+hash+']')qui recherchera l'élément par id en premier, et n'aura recours à la recherche du a que s'il n'est pas trouvé.
gnarf

@gnarf - Il n'est pas nécessaire d'optimiser les sélecteurs '#' dans jQuery - ils sont déjà optimisés pour vous. Il est assez facile de voir si vous avez lu le code source de jQuery.
CodeJoust

3
@CodeJoust - Je fais partie de l'équipe jQuery, je l'ai lu plusieurs fois, et oui $("#selector")est optimisé mais $("#selector,a[name='selector']")ne passera pas par les mêmes optimisations aussi rapidement. Je suppose que mon commentaire de 2,5 ans est un peu étrange. L '"optimisation" évite la a[name='selector']recherche si elle trouve l'identifiant, pas l'optimisation de la recherche de l'identifiant.
gnarf

1
J'ai eu de la chance avec cette approche: <a data-hash="about"> À propos </a> <script> $ ("[data-hash]"). Click (function () {var data = $ (this) .attr ("data-hash"); $ (document.body) .animate ({'scrollTop': $ ("#" + data) .offset (). top}, 500);}); </script>
Jazzy

33

Excellente solution par jAndy, mais le défilement fluide semble avoir des problèmes de fonctionnement dans Firefox.

L'écrire de cette façon fonctionne également dans Firefox.

(function($) {
    $(document).ready(function() {
         $('html, body').animate({
           'scrollTop':   $('#anchorName2').offset().top
         }, 2000);
    });
})(jQuery);

Dans la dernière version de Chrome, c'est la seule méthode que j'ai trouvée qui fonctionne de manière cohérente. Merci pour le conseil!
génial

32

Pure js 2018-2020:

Il existe un moyen très pratique de faire défiler jusqu'à l'élément:

el.scrollIntoView({
  behavior: 'smooth', // smooth scroll
  block: 'start' // the upper border of the element will be aligned at the top of the visible part of the window of the scrollable area.
})

Mais pour autant que je comprends, il n'a pas un tel soutien que les options ci-dessous.

entrez la description de l'image ici

En savoir plus sur la méthode.


S'il est nécessaire que l'élément soit en haut:

const element = document.querySelector('#element')
const topPos = element.getBoundingClientRect().top + window.pageYOffset

window.scrollTo({
  top: topPos, // scroll so that the element is at the top of the view
  behavior: 'smooth' // smooth scroll
})

Exemple de démonstration sur Codepen


Si vous souhaitez que l'élément soit au centre:

const element = document.querySelector('#element')
const rect = element.getBoundingClientRect() // get rects(width, height, top, etc)
const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

window.scroll({
  top: rect.top + rect.height / 2 - viewHeight / 2,
  behavior: 'smooth' // smooth scroll
});

Exemple de démonstration sur Codepen


Soutien:

введите сюда описание изображения

Ils écrivent que scrollc'est la même méthode que scrollTo, mais le support montre mieux dansscrollTo .

En savoir plus sur la méthode


Cette solution fonctionne très très bien! Merci d'avoir partagé!
génial

29

Une solution javascript pure sans JQuery. Testé sur Chrome & Ie, non testé sur IOS

function ScrollTo(name) {
  ScrollToResolver(document.getElementById(name));
}

function ScrollToResolver(elem) {
  var jump = parseInt(elem.getBoundingClientRect().top * .2);
  document.body.scrollTop += jump;
  document.documentElement.scrollTop += jump;
  if (!elem.lastjump || elem.lastjump > Math.abs(jump)) {
    elem.lastjump = Math.abs(jump);
    setTimeout(function() { ScrollToResolver(elem);}, "100");
  } else {
    elem.lastjump = null;
  }
}

démo: https://jsfiddle.net/jd7q25hg/12/


1
Toutes mes excuses pour avoir commenté un ancien sujet, mais cela fonctionne mieux pour moi car mon projet n'utilise pas JQuery. Le seul problème que j'ai remarqué est qu'il manque environ 5 pixels si vous faites défiler vers le haut.
AntBirch

Très rafraîchissant de voir une version pure js. J'enseigne aux étudiants à toujours regarder sous le capot et à comprendre ce que JQuery fait pour eux, c'est donc un bel exemple.
Dave Everitt

2
Cela devrait être la réponse acceptée: c'est un pur exemple js ET il réalise l'effet d'animation de défilement souhaité. J'ai ajusté la valeur du délai d'attente à 20 et cela fonctionne parfaitement.
Mark Barrasso

Merci j'adore les solutions javascript pures
R01010010

2
Fonctionne dans IOS vient de le tester.
Debbie Kurth

23

En 2018, vous n'avez pas besoin de jQuery pour quelque chose de simple comme ça. La scrollIntoView()méthode intégrée prend en charge une behaviorpropriété " " pour faire défiler en douceur vers n'importe quel élément de la page. Vous pouvez même mettre à jour l'URL du navigateur avec un hachage pour le mettre en signet.

À partir de ce didacticiel sur le défilement des signets HTML , voici une façon native d'ajouter automatiquement un défilement fluide à tous les liens d'ancrage sur votre page:

let anchorlinks = document.querySelectorAll('a[href^="#"]')
 
for (let item of anchorlinks) { // relitere 
    item.addEventListener('click', (e)=> {
        let hashval = item.getAttribute('href')
        let target = document.querySelector(hashval)
        target.scrollIntoView({
            behavior: 'smooth',
            block: 'start'
        })
        history.pushState(null, null, hashval)
        e.preventDefault()
    })
}

2
Excellente réponse qui supprime la dépendance à jQuery
zai chang

Hou la la! Fonctionne très bien!
Alexandru Trandafir Catalin

14

Faites défiler en douceur jusqu'à la bonne position (2019)

Obtenez des y coordonnées et une utilisation correcteswindow.scrollTo({top: y, behavior: 'smooth'})

const id = 'anchorName2';
const yourElement = document.getElementById(id);
const y = yourElement.getBoundingClientRect().top + window.pageYOffset;

window.scrollTo({top: y, behavior: 'smooth'});

Avec décalage

scrollIntoViewest également une bonne option, mais elle peut ne pas fonctionner parfaitement dans certains cas. Par exemple, lorsque vous avez besoin d'un décalage supplémentaire . Avec scrollTovous avez juste besoin d'ajouter ce décalage comme ceci:

const yOffset = -10; 

window.scrollTo({top: y + yOffset, behavior: 'smooth'});

Je pense que vous devriez ajouter ce qui suit au fichier de style CSS: css html { scroll-behavior: smooth; }
parismiguel

5
$(document).ready ->
  $("a[href^='#']").click ->
    $(document.body).animate
      scrollTop: $($(this).attr("href")).offset().top, 1000

5

La solution de CSS-Tricks ne fonctionne plus dans jQuery 2.2.0. Cela générera une erreur de sélection:

Erreur d'exécution JavaScript: erreur de syntaxe, expression non reconnue: a [href * = #]: not ([href = #])

Je l'ai corrigé en changeant le sélecteur. L'extrait complet est le suivant:

$(function() {
  $("a[href*='#']:not([href='#'])").click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
    var target = $(this.hash);
    target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
    if (target.length) {
      $('html,body').animate({
        scrollTop: target.offset().top
      }, 1000);
      return false;
    }
  }
 });
});

4

La plupart des réponses sont inutilement compliquées.

Si vous voulez simplement passer à l'élément cible, vous n'avez pas besoin de JavaScript:

# the link:
<a href="#target">Click here to jump.</a>

# target element:
<div id="target">Any kind of element.</div>

Si vous souhaitez faire défiler la cible avec animation , veuillez vous référer à la réponse de @ Shahil.


Parfois, cependant, vous devez le faire dynamiquement; c'est-à-dire sans aucune action directe de l'utilisateur. Je pense que c'est ce que souhaite le PO.
jpaugh

1
Oui, il est clair que l'OP était déjà au courant de la fonctionnalité de lien d'ancrage.
isherwood


3

Il s'agit d'un script de travail qui fera défiler la page jusqu'à l'ancre. Pour configurer, donnez simplement au lien d'ancre un identifiant qui correspond à l'attribut name de l'ancre à laquelle vous souhaitez faire défiler.

<script>
jQuery(document).ready(function ($){ 
 $('a').click(function (){ 
  var id = $(this).attr('id');
  console.log(id);
  if ( id == 'cet' || id == 'protein' ) {
   $('html, body').animate({ scrollTop: $('[name="' + id + '"]').offset().top}, 'slow'); 
  }
 }); 
});
</script>

2

Je sais que cette question est vraiment ancienne, mais j'ai trouvé une solution jQuery facile et simple dans css-tricks . C'est celui que j'utilise maintenant.

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});

1
Le sélecteur lève une exception dans jquery 2.2.0. 0x800a139e - Erreur d'exécution JavaScript: erreur de syntaxe, expression non reconnue: a [href * = #]: not ([href = #])
Bill Shihara

2

jQuery("a[href^='#']").click(function(){
    jQuery('html, body').animate({
        scrollTop: jQuery( jQuery(this).attr('href') ).offset().top
    }, 1000);
    return false;
});


2

une solution vue2 ... ajouter une propriété de données simple pour forcer simplement la mise à jour

  const app = new Vue({ 
  ... 

  , updated: function() {
           this.$nextTick(function() {
           var uri = window.location.href
           var anchor = ( uri.indexOf('#') === -1 ) ? '' : uri.split('#')[1]
           if ( String(anchor).length > 0 && this.updater === 'page_load' ) {
              this.updater = "" // only on page-load !
              location.href = "#"+String(anchor)
           }
         })
        }
     });
     app.updater = "page_load"

 /* smooth scrolling in css - works in html5 only */
 html, body {
     scroll-behavior: smooth;
 }

0

la façon la plus simple de faire défiler la page jusqu'à une ancre donnée est de taper votre style.css * {scroll-behavior: smooth;} et dans votre navigation html, utilisez #NameOfTheSection

*{scroll-behavior: smooth;}
<a href="#scroll-to">Home<a/>

<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>

<section id="scroll-to">
<p>it will scroll down to this section</p>
</section>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.