web-dev-qa-db-fra.com

jQuery défiler jusqu'à l'élément

J'ai cet élément input:

<input type="text" class="textfield" value="" id="subject" name="subject">

Ensuite, j'ai d'autres éléments, comme d'autres entrées de texte, textareas, etc.

Lorsque l'utilisateur clique sur cette input avec #subject, la page doit défiler jusqu'au dernier élément de la page avec une animation de Nice. Ce devrait être un parchemin vers le bas et non vers le haut.

Le dernier élément de la page est un bouton submit avec #submit:

<input type="submit" class="submit" id="submit" name="submit" value="Ok, Done.">

L'animation ne devrait pas être trop rapide et devrait être fluide.

J'utilise la dernière version de jQuery. Je préfère ne pas installer de plug-in, mais utiliser les fonctionnalités par défaut de jQuery pour y parvenir.

2139
DiegoP.

En supposant que vous ayez un bouton avec l'id button, essayez cet exemple:

$("#button").click(function() {
    $([document.documentElement, document.body]).animate({
        scrollTop: $("#elementtoScrollToID").offset().top
    }, 2000);
});

J'ai eu le code de l'article Faites défiler en douceur jusqu'à un élément sans un plugin jQuery. Et je l'ai testé sur l'exemple ci-dessous.

<html>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
    <script>
        $(document).ready(function (){
            $("#click").click(function (){
                $('html, body').animate({
                    scrollTop: $("#div1").offset().top
                }, 2000);
            });
        });
    </script>
    <div id="div1" style="height: 1000px; width 100px">
        Test
    </div>
    <br/>
    <div id="div2" style="height: 1000px; width 100px">
        Test 2
    </div>
    <button id="click">Click me</button>
</html>
3809
Steve

jQuery .scrollTo() Method

jQuery .scrollTo (): Affichage - Démo, API, Source

J'ai écrit ce plugin léger pour rendre le défilement page/élément beaucoup plus facile. Il est flexible où vous pouvez transmettre un élément cible ou une valeur spécifiée. Peut-être que cela pourrait faire partie de la prochaine version officielle de jQuery, qu'en pensez-vous?


Exemples Utilisation:

$('body').scrollTo('#target'); // Scroll screen to target element

$('body').scrollTo(500); // Scroll screen 500 pixels down

$('#scrollable').scrollTo(100); // Scroll individual element 100 pixels down

Options:

scrollTarget : élément, chaîne ou nombre indiquant la position de défilement souhaitée.

offsetTop : nombre définissant un espacement supplémentaire au-dessus de la cible de défilement.

duration : chaîne ou nombre déterminant la durée d'exécution de l'animation.

easing : chaîne indiquant la fonction d'accélération à utiliser pour la transition.

complete : fonction à appeler une fois l'animation terminée.

496
Timothy Perez

Si vous n'êtes pas très intéressé par l'effet de défilement lisse et que vous êtes intéressé par le défilement d'un élément particulier, vous n'avez pas besoin d'une fonction jQuery pour cela. Javascript a votre cas couvert:

https://developer.mozilla.org/en-US/docs/Web/API/element.scrollIntoView

Donc, tout ce que vous avez à faire est: $("selector").get(0).scrollIntoView();

.get(0) est utilisé parce que nous voulons récupérer l'élément DOM de JavaScript et non l'élément DOM de JQuery.

336
Atharva

Utiliser ce script simple

if($(window.location.hash).length > 0){
        $('html, body').animate({ scrollTop: $(window.location.hash).offset().top}, 1000);
}

Faire en sorte que si une balise de hachage est trouvée dans l'URL, le scrollTo animer à l'ID. Si aucune balise de hachage n'a été trouvée, ignorez le script.

42
Warface
jQuery(document).ready(function($) {
  $('a[href^="#"]').bind('click.smoothscroll',function (e) {
    e.preventDefault();
    var target = this.hash,
        $target = $(target);

    $('html, body').stop().animate( {
      'scrollTop': $target.offset().top-40
    }, 900, 'swing', function () {
      window.location.hash = target;
    } );
  } );
} );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<ul role="tablist">
  <li class="active" id="p1"><a href="#pane1" role="tab">Section 1</a></li>
  <li id="p2"><a href="#pane2" role="tab">Section 2</a></li>
  <li id="p3"><a href="#pane3" role="tab">Section 3</a></li>
</ul>

<div id="pane1"></div>
<div id="pane2"></div>
<div id="pane3"></div>
31
davidcondrey

La solution de Steve et Peter fonctionne très bien.

Mais dans certains cas, vous devrez peut-être convertir la valeur en entier. Étrangement, la valeur renvoyée par $("...").offset().top est parfois dans float.
Utilisation: parseInt($("....").offset().top)

Par exemple:

$("#button").click(function() {
    $('html, body').animate({
        scrollTop: parseInt($("#elementtoScrollToID").offset().top)
    }, 2000);
});
23
Tejasvi Hegde

Une version compacte de la solution "animate".

$.fn.scrollTo = function (speed) {
    if (typeof(speed) === 'undefined')
        speed = 1000;

    $('html, body').animate({
        scrollTop: parseInt($(this).offset().top)
    }, speed);
};

Utilisation de base: $('#your_element').scrollTo();

19
Rezgar Cadro

Si vous ne gérez que le défilement vers un élément d’entrée, vous pouvez utiliser focus(). Par exemple, si vous voulez faire défiler la première entrée visible:

$(':input:visible').first().focus();

Ou la première entrée visible dans un conteneur de classe .error:

$('.error :input:visible').first().focus();

Merci à Tricia Ball pour l'avoir signalé!

16
Benjamin Oakes

Avec cette solution vous n’avez besoin d’aucun plugin et il y a aucune configuration requise en plus de placer le script avant votre balise de fermeture </body> _.

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

if ($(window.location.hash).length > 1) {
  $("html, body").animate({
    scrollTop: $(window.location.hash).offset().top
  }, 1000);
}

Au chargement, s'il y a un dièse dans l'adresse, nous le faisons défiler.

Et - chaque fois que vous cliquez sur un lien a avec un hachage href, par ex. #top, nous le faisons défiler.

15
Jonathan

Je connais un chemin sans jQuery:

document.getElementById("element-id").scrollIntoView();
11
GameMaster1928

Dans la plupart des cas, il serait préférable d'utiliser un plugin. Sérieusement. Je vais tout à moi ici . Bien sûr, il y en a d'autres aussi. Mais s'il vous plaît vérifiez s'ils évitent vraiment les pièges pour lesquels vous voudriez un plugin en premier lieu - ils ne le font pas tous.

J'ai écrit sur les raisons d'utiliser un plugin ailleurs . En un mot, la doublure qui sous-tend la plupart des réponses ici

$('html, body').animate( { scrollTop: $target.offset().top }, duration );

est mauvais UX.

  • L'animation ne répond pas aux actions de l'utilisateur. Il continue même si l'utilisateur clique, tape ou essaie de faire défiler.

  • Si le point de départ de l'animation est proche de l'élément cible, l'animation est extrêmement lente.

  • Si l'élément cible est placé près du bas de la page, vous ne pouvez pas le faire défiler vers le haut de la fenêtre. L'animation de défilement s'arrête brusquement puis, au milieu du mouvement.

Pour gérer ces problèmes (et un groupe d'autres ), vous pouvez utiliser l'un de mes plugins, jQuery.scrollable . L'appel devient alors

$( window ).scrollTo( targetPosition );

et c'est tout. Bien sûr, il y a plus d'options .

En ce qui concerne la position cible, $target.offset().top effectue le travail dans la plupart des cas. Sachez toutefois que la valeur renvoyée ne prend pas en compte une bordure sur l’élément html ( voir cette démonstration ). Si vous souhaitez que la position cible soit précise en toutes circonstances, il est préférable d'utiliser

targetPosition = $( window ).scrollTop() + $target[0].getBoundingClientRect().top;

Cela fonctionne même si une bordure sur l'élément html est définie.

7
hashchange

Si vous souhaitez faire défiler un conteneur de débordement (au lieu de $('html, body') réponse ci-dessus), en utilisant également le positionnement absolu, procédez comme suit:

var elem = $('#myElement'),
    container = $('#myScrollableContainer'),
    pos = elem.position().top + container.scrollTop() - container.position().top;

container.animate({
  scrollTop: pos
}
6
FAjir

Un plugin jQuery personnalisé très simple et facile à utiliser. Ajoutez simplement l'attribut scroll= à votre élément cliquable et définissez sa valeur sur le sélecteur vers lequel vous souhaitez faire défiler.

Comme si: <a scroll="#product">Click me</a>. Il peut être utilisé sur n'importe quel élément.

(function($){
    $.fn.animateScroll = function(){
        console.log($('[scroll]'));
        $('[scroll]').click(function(){
            selector = $($(this).attr('scroll'));
            console.log(selector);
            console.log(selector.offset().top);
            $('html body').animate(
                {scrollTop: (selector.offset().top)}, //- $(window).scrollTop()
                1000
            );
        });
    }
})(jQuery);

// RUN
jQuery(document).ready(function($) {
    $().animateScroll();
});

// IN HTML EXAMPLE
// RUN ONCLICK ON OBJECT WITH ATTRIBUTE SCROLL=".SELECTOR"
// <a scroll="#product">Click To Scroll</a>
5
DevWL

C’est mon approche qui consiste à résumer les identifiants et href, en utilisant un sélecteur de classe générique.

$(function() {
  // Generic selector to be used anywhere
  $(".js-scroll-to").click(function(e) {

    // Get the href dynamically
    var destination = $(this).attr('href');

    // Prevent href=“#” link from changing the URL hash (optional)
    e.preventDefault();

    // Animate scroll to destination
    $('html, body').animate({
      scrollTop: $(destination).offset().top
    }, 500);
  });
});
<!-- example of a fixed nav menu -->
<ul class="nav">
  <li>
    <a href="#section-1" class="nav-item js-scroll-to">Item 1</a>
  </li>
  <li>
    <a href="#section-2" class="nav-item js-scroll-to">Item 2</a>
  </li>
  <li>
    <a href="#section-3" class="nav-item js-scroll-to">Item 3</a>
  </li>
</ul>
5
vascogaspar

Un moyen facile pour faire défiler la page pour cibler div id

var targetOffset = $('#divID').offset().top;
$('html, body').animate({scrollTop: targetOffset}, 1000);
5
Irshad Khan

Animations:

// slide to top of the page
$('.up').click(function () {
    $("html, body").animate({
        scrollTop: 0
    }, 600);
    return false;
});

// slide page to anchor
$('.menutop b').click(function(){
    //event.preventDefault();
    $('html, body').animate({
        scrollTop: $( $(this).attr('href') ).offset().top
    }, 600);
    return false;
});

// Scroll to class, div
$("#button").click(function() {
    $('html, body').animate({
        scrollTop: $("#target-element").offset().top
    }, 1000);
});

// div background animate
$(window).scroll(function () {

    var x = $(this).scrollTop();

    // freezze div background
    $('.banner0').css('background-position', '0px ' + x +'px');

    // from left to right
    $('.banner0').css('background-position', x+'px ' +'0px');

    // from right to left
    $('.banner0').css('background-position', -x+'px ' +'0px');

    // from bottom to top
    $('#skills').css('background-position', '0px ' + -x + 'px');

    // move background from top to bottom
    $('.skills1').css('background-position', '0% ' + parseInt(-x / 1) + 'px' + ', 0% ' + parseInt(-x / 1) + 'px, center top');

    // Show hide mtop menu  
    if ( x > 100 ) {
    $( ".menu" ).addClass( 'menushow' );
    $( ".menu" ).fadeIn("slow");
    $( ".menu" ).animate({opacity: 0.75}, 500);
    } else {
    $( ".menu" ).removeClass( 'menushow' );
    $( ".menu" ).animate({opacity: 1}, 500);
    }

});

// progres bar animation simple
$('.bar1').each(function(i) {
  var width = $(this).data('width');  
  $(this).animate({'width' : width + '%' }, 900, function(){
    // Animation complete
  });  
});
5
user7601056

C'est comme ça que je le fais.

document.querySelector('scrollHere').scrollIntoView({ behavior: 'smooth' })

Fonctionne dans n'importe quel navigateur.

Il peut facilement être intégré à une fonction

function scrollTo(selector) {
    document.querySelector(selector).scrollIntoView({ behavior: 'smooth' })
}

Voici un exemple de travail

$(".btn").click(function() {
  document.getElementById("scrollHere").scrollIntoView( {behavior: "smooth" })
})
.btn {margin-bottom: 500px;}
.middle {display: block; margin-bottom: 500px; color: red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button class="btn">Scroll down</button>

<h1 class="middle">You see?</h1>

<div id="scrollHere">Arrived at your destination</div>

Docs

4
Edvard Åkerberg

$('html, body').animate(...) ne fonctionne pas pour moi sur iphone, Android chrome navigateur Safari.

Je devais cibler l'élément de contenu racine de la page.

$ ('# cotnent'). animate (...)

Voici ce que j'ai fini avec

if (navigator.userAgent.match(/(iPod|iPhone|iPad|Android)/)) {           
    $('#content').animate({
    scrollTop: $("#elementtoScrollToID").offset().top
   }, 'slow');
}
else{
    $('html, body').animate({
    scrollTop: $("#elementtoScrollToID").offset().top
    }, 'slow');
}

Tout le contenu du corps câblé avec une div #content

<html>
....
<body>
<div id="content">
....
</div>
</body>
</html>
4
Shahdat
var scrollTo = function($parent, $element) {
    var topDiff = $element.position().top - $parent.position().top;

    $parent.animate({
        scrollTop : topDiff
    }, 100);
};
4
kayz1

C'est la réponse d'Atharva de: https://developer.mozilla.org/en-US/docs/Web/API/element.scrollIntoView . Je voulais juste ajouter si votre document est dans une iframe, vous pouvez choisir un élément dans le cadre parent à faire défiler dans la vue:

 $('#element-in-parent-frame', window.parent.document).get(0).scrollIntoView();
3
cynya
jQuery(document).ready(function($) {
  $('a[href^="#"]').bind('click.smoothscroll',function (e) {
    e.preventDefault();
    var target = this.hash,
        $target = $(target);

    $('html, body').stop().animate( {
      'scrollTop': $target.offset().top-40
    }, 900, 'swing', function () {
      window.location.hash = target;
    } );
  } );
} );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<ul role="tablist">
  <li class="active" id="p1"><a href="#pane1" role="tab">Section 1</a></li>
  <li id="p2"><a href="#pane2" role="tab">Section 2</a></li>
  <li id="p3"><a href="#pane3" role="tab">Section 3</a></li>
</ul>

<div id="pane1"></div>
<div id="pane2"></div>
<div id="pane3"></div>
3
Minguocode

J'ai mis en place un module scroll-elementnpm install scroll-element. Cela fonctionne comme ceci:

import { scrollToElement, scrollWindowToElement } from 'scroll-element'

/* scroll the window to your target element, duration and offset optional */
let targetElement = document.getElementById('my-item')
scrollWindowToElement(targetElement)

/* scroll the overflow container element to your target element, duration and offset optional */
let containerElement = document.getElementById('my-container')
let targetElement = document.getElementById('my-item')
scrollToElement(containerElement, targetElement)

Écrit avec l'aide des SO messages suivants:

Voici le code:

export const scrollToElement = function(containerElement, targetElement, duration, offset) {
  if (duration == null) { duration = 1000 }
  if (offset == null) { offset = 0 }

  let targetOffsetTop = getElementOffset(targetElement).top
  let containerOffsetTop = getElementOffset(containerElement).top
  let scrollTarget = targetOffsetTop + ( containerElement.scrollTop - containerOffsetTop)
  scrollTarget += offset
  scroll(containerElement, scrollTarget, duration)
}

export const scrollWindowToElement = function(targetElement, duration, offset) {
  if (duration == null) { duration = 1000 }
  if (offset == null) { offset = 0 }

  let scrollTarget = getElementOffset(targetElement).top
  scrollTarget += offset
  scrollWindow(scrollTarget, duration)
}

function scroll(containerElement, scrollTarget, duration) {
  let scrollStep = scrollTarget / (duration / 15)
  let interval = setInterval(() => {
    if ( containerElement.scrollTop < scrollTarget ) {
      containerElement.scrollTop += scrollStep
    } else {
      clearInterval(interval)
    }
  },15)
}

function scrollWindow(scrollTarget, duration) {
  let scrollStep = scrollTarget / (duration / 15)
  let interval = setInterval(() => {
    if ( window.scrollY < scrollTarget ) {
      window.scrollBy( 0, scrollStep )
    } else {
      clearInterval(interval)
    }
  },15)
}

function getElementOffset(element) {
  let de = document.documentElement
  let box = element.getBoundingClientRect()
  let top = box.top + window.pageYOffset - de.clientTop
  let left = box.left + window.pageXOffset - de.clientLeft
  return { top: top, left: left }
}
2
svnm

Cela a fonctionné pour moi:

var targetOffset = $('#elementToScrollTo').offset().top;
$('#DivParent').animate({scrollTop: targetOffset}, 2500);
2
Polaris
$('html, body').animate({scrollTop: 
  Math.min( 
    $(to).offset().top-margintop, //margintop is the margin above the target
    $('body')[0].scrollHeight-$('body').height()) //if the target is at the bottom
}, 2000);
2
user669677

J'ai écrit une fonction d'usage général qui fait défiler un objet jQuery, un sélecteur CSS ou une valeur numérique.

Exemple d'utilisation:

// scroll to "#target-element":
$.scrollTo("#target-element");

// scroll to 80 pixels above first element with class ".invalid":
$.scrollTo(".invalid", -80);

// scroll a container with id "#my-container" to 300 pixels from its top:
$.scrollTo(300, 0, "slow", "#my-container");

Le code de la fonction:

/**
* Scrolls the container to the target position minus the offset
*
* @param target    - the destination to scroll to, can be a jQuery object
*                    jQuery selector, or numeric position
* @param offset    - the offset in pixels from the target position, e.g.
*                    pass -80 to scroll to 80 pixels above the target
* @param speed     - the scroll speed in milliseconds, or one of the
*                    strings "fast" or "slow". default: 500
* @param container - a jQuery object or selector for the container to
*                    be scrolled. default: "html, body"
*/
jQuery.scrollTo = function (target, offset, speed, container) {

    if (isNaN(target)) {

        if (!(target instanceof jQuery))
            target = $(target);

        target = parseInt(target.offset().top);
    }

    container = container || "html, body";
    if (!(container instanceof jQuery))
        container = $(container);

    speed = speed || 500;
    offset = offset || 0;

    container.animate({
        scrollTop: target + offset
    }, speed);
};
2
isapir

Pour afficher l'élément complet (si cela est possible avec la taille de la fenêtre actuelle):

var element       = $("#some_element");
var elementHeight = element.height();
var windowHeight  = $(window).height();

var offset = Math.min(elementHeight, windowHeight) + element.offset().top;
$('html, body').animate({ scrollTop: offset }, 500);
2
Roman Shamritskiy

Lorsque l'utilisateur clique sur cette entrée avec #subject, la page doit défiler jusqu'au dernier élément de la page avec une animation de Nice. Ce devrait être un parchemin vers le bas et non vers le haut.

Le dernier élément de la page est un bouton d'envoi avec #submit

$('#subject').click(function()
{
    $('#submit').focus();
    $('#subject').focus();
});

Cela fera d’abord défiler jusqu’à #submit puis ramènera le curseur sur l’entrée sur laquelle vous avez cliqué, ce qui simule un défilement vers le bas et fonctionne avec la plupart des navigateurs. De plus, jQuery n'est pas nécessaire car il peut être écrit en JavaScript pur.

Ce mode d'utilisation de la fonction focus peut-il imiter l'animation d'une meilleure façon, en chaînant les appels focus? Je n'ai pas testé cette théorie, mais elle ressemblerait à ceci:

<style>
  #F > *
  {
    width: 100%;
  }
</style>

<form id="F" >
  <div id="child_1"> .. </div>
  <div id="child_2"> .. </div>
  ..
  <div id="child_K"> .. </div>
</form>

<script>
  $('#child_N').click(function()
  {
    $('#child_N').focus();
    $('#child_N+1').focus();
    ..
    $('#child_K').focus();

    $('#child_N').focus();
  });
</script>
2
Khaled.K

Pour ce que cela vaut, c’est ainsi que j’ai réussi à obtenir un tel comportement pour un élément général qui peut être à l’intérieur d’une DIV avec défilement. Dans notre cas, nous ne faisons pas défiler tout le corps, mais seulement des éléments particuliers avec débordement: auto; dans une plus grande mise en page.

Il crée une fausse entrée de la hauteur de l'élément cible, puis le met en évidence, et le navigateur se préoccupe du reste, quelle que soit la profondeur de votre hiérarchie. Fonctionne comme un charme.

var $scrollTo = $('#someId'),
inputElem = $('<input type="text"></input>');

$scrollTo.prepend(inputElem);
inputElem.css({
  position: 'absolute',
  width: '1px',
  height: $scrollTo.height()
});
inputElem.focus();
inputElem.remove();
2
martinh_kentico

Réponse mise à jour à compter de 2019:

$('body').animate({
    scrollTop: $('#subject').offset().top - $('body').offset().top + $('body').scrollTop()
}, 'fast');
1
kejodion