Faites défiler en douceur jusqu'à un div spécifique en cliquant

91

Ce que j'essaie de faire, c'est de faire en sorte que si vous cliquez sur un bouton, il défile vers le bas (en douceur) jusqu'à un div spécifique sur la page.

Ce dont j'ai besoin, c'est que si vous cliquez sur le bouton, il défile en douceur jusqu'à la div «seconde».

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}
<div class="first"><button type="button">Click Me!</button></div>
<div class="second">Hi</div>

Erik Fischer
la source
Vous pouvez essayer ce plugin Bien que celui-ci soit beaucoup plus convivial. Il vous suffit de lier le fichier JS dans l'en-tête et de modifier votre balisage de manière appropriée pour qu'il fonctionne.
joshrathke
1
cela devrait vous aider :: stackoverflow.com/questions/3432656/…
Sudhir Bastakoti

Réponses:

177

faire:

$("button").click(function() {
    $('html,body').animate({
        scrollTop: $(".second").offset().top},
        'slow');
});

Jsfiddle mis à jour

Sudhir Bastakoti
la source
Utilisez-vous javaScript ici ou jQuery?
1
@FahadUddin son jQuery.
Sudhir Bastakoti
@SudhirBastakoti: Pourquoi le JsFiddle n'a-t-il pas inclus la bibliothèque jquery pour cela sur cette page?
@Sudhir Bastakoti mais de nombreux utilisateurs se plaignent que le défilement n'est pas fluide.
Maulik
39

Il existe de nombreux exemples de défilement fluide à l'aide de bibliothèques JS telles que jQuery, Mootools, Prototype, etc.

L'exemple suivant est sur du JavaScript pur. Si vous n'avez pas de jQuery / Mootools / Prototype sur la page ou si vous ne voulez pas surcharger la page avec de lourdes bibliothèques JS, l'exemple vous sera utile.

http://jsfiddle.net/rjSfP/

Partie HTML:

<div class="first"><button type="button" onclick="smoothScroll(document.getElementById('second'))">Click Me!</button></div>
<div class="second" id="second">Hi</div>

Partie CSS:

.first {
    width: 100%;
    height: 1000px;
    background: #ccc;
}

.second {
    width: 100%;
    height: 1000px;
    background: #999;
}

Partie JS:

window.smoothScroll = function(target) {
    var scrollContainer = target;
    do { //find scroll container
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do { //find the top of target relatively to the container
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    scroll = function(c, a, b, i) {
        i++; if (i > 30) return;
        c.scrollTop = a + (b - a) / 30 * i;
        setTimeout(function(){ scroll(c, a, b, i); }, 20);
    }
    // start scrolling
    scroll(scrollContainer, scrollContainer.scrollTop, targetY, 0);
}
Nico
la source
J'utilise ceci et cela fonctionne très bien. Comment puis-je ralentir le défilement?
jamescampbell
Une idée comment ajouter un décalage pour la barre de navigation fixe dans ce code? Voici l'exemple que j'ai fait du violon
Plavookac
3
Encore utile après 5 ans
Owaiz Yusufi
9

J'ai joué un peu avec la réponse de nico et c'était nerveux. J'ai fait un peu d'enquête et j'ai trouvé window.requestAnimationFramequelle fonction est appelée à chaque cycle de repeinture. Cela permet une animation plus propre. J'essaie toujours de se concentrer sur de bonnes valeurs par défaut pour la taille des pas, mais pour mon exemple, les choses semblent plutôt bonnes en utilisant cette implémentation.

var smoothScroll = function(elementId) {
    var MIN_PIXELS_PER_STEP = 16;
    var MAX_SCROLL_STEPS = 30;
    var target = document.getElementById(elementId);
    var scrollContainer = target;
    do {
        scrollContainer = scrollContainer.parentNode;
        if (!scrollContainer) return;
        scrollContainer.scrollTop += 1;
    } while (scrollContainer.scrollTop == 0);

    var targetY = 0;
    do {
        if (target == scrollContainer) break;
        targetY += target.offsetTop;
    } while (target = target.offsetParent);

    var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
                                 (targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

    var stepFunc = function() {
        scrollContainer.scrollTop =
            Math.min(targetY, pixelsPerStep + scrollContainer.scrollTop);

        if (scrollContainer.scrollTop >= targetY) {
            return;
        }

        window.requestAnimationFrame(stepFunc);
    };

    window.requestAnimationFrame(stepFunc);
}
Ned Rockson
la source
1
@Alfonso Voir ci-dessus. Il s'agit simplement d'une version optimisée du code de nico dans une réponse précédente.
Ned Rockson
@NedRockson Ne fonctionne pas pour moi donne le message de console "Uncaught TypeError: Impossible de lire la propriété 'parentNode' de null" mais le code de nico fonctionne, que dois-je faire pour pouvoir appliquer une animation propre?
Kartik Watwani
@KartikWatwani Cela signifie que lors de la lecture de la ligne scrollContainer = scrollContainer.parentNode, scrollContainer est nul. Cela signifie probablement que vous ne transmettez pas la valeur correcte elementIdlors de l'appel de cette fonction. Il est également possible que vous exécutiez ce script sur une page où cet elementId n'existe pas.
Ned Rockson
@NedRockson Si j'avais elementIdeu tort, j'aurais reçu la même erreur dans le cas de l'exemple de @nico, mais dans ce cas, le défilement fonctionne mais pas correctement.
Kartik Watwani
Utiliser requestAnimationFrameau lieu de setTimeoutest la voie à suivre. setTimeoutne doit pas être utilisé pour les animations.
tsnkff
2

J'ai pris la version de Ned Rockson et je l' ai ajustée pour permettre également les défilements vers le haut.

var smoothScroll = function(elementId) {
  var MIN_PIXELS_PER_STEP = 16;
  var MAX_SCROLL_STEPS = 30;
  var target = document.getElementById(elementId);
  var scrollContainer = target;
  do {
    scrollContainer = scrollContainer.parentNode;
    if (!scrollContainer) return;
    scrollContainer.scrollTop += 1;
  } while (scrollContainer.scrollTop === 0);

  var targetY = 0;
  do {
    if (target === scrollContainer) break;
    targetY += target.offsetTop;
  } while (target = target.offsetParent);

  var pixelsPerStep = Math.max(MIN_PIXELS_PER_STEP,
    Math.abs(targetY - scrollContainer.scrollTop) / MAX_SCROLL_STEPS);

  var isUp = targetY < scrollContainer.scrollTop;

  var stepFunc = function() {
    if (isUp) {
      scrollContainer.scrollTop = Math.max(targetY, scrollContainer.scrollTop - pixelsPerStep);
      if (scrollContainer.scrollTop <= targetY) {
        return;
      }
    } else {
        scrollContainer.scrollTop = Math.min(targetY, scrollContainer.scrollTop + pixelsPerStep);

      if (scrollContainer.scrollTop >= targetY) {
        return;
      }
    }

    window.requestAnimationFrame(stepFunc);
  };

  window.requestAnimationFrame(stepFunc);
};
Marek Lisý
la source
2

Vous pouvez utiliser le CSS de base pour obtenir un défilement fluide

html {
  scroll-behavior: smooth;
}
Sardorbek Khalimov
la source