简体   繁体   中英

Strange behavor using scrollTop

I've a strange behavor using scrollTop JQuery function. I've a div that contains a complex text divided in different sections like this:

<div id="wrapper" ... >
    <div id="section1">
        <h1>Section 1</h1>
        Lorem ipsum dolor sit amet, consectetuer... 
        ...
    </div>
    <div id="section2">
        <h1>Section 2</h1>
        Lorem ipsum dolor sit amet, consectetuer... 
        ...
    </div>
    <div id="section3">
        <h1>Section 3</h1>
        Lorem ipsum dolor sit amet, consectetuer... 
        ...
    </div>
    ...

a second DIV contains a simple list of sections and when user click on each of them I want wrapper scroll at the right section:

<li>
   <a href="#" onclick="customScrollTo('section1')">section1</a>
</li>
<li>
   <a href="#" onclick="customScrollTo('section2')">section2</a>
...

and this is simple the JS function:

function customScrollTo (section) {

     $('#wrapper').animate({
         scrollTop: $("#wrapper div[id='" + section + "']").offset().top
     }, 200);
};

now if you try to test it in this JSfiddle: http://jsfiddle.net/Ws5F9/4/

you can see two strange behavors:

  1. if you click 'section 1' than 'section 2' than 'section 3', section 3 doesn't work!
  2. if you click twice on the same section link, the second time it scroll at page top

There are two problems with the customScrollTo method.

First, you are using .offset() instead of .position() . This is returning the position relative to the document rather than the #wrapper div. This is barely noticeable here because the div is close to the top of the document anyway, but you'd run into trouble as you moved it further down the page.

Second, when you call position it is going to return the position of the element taking into account the current scroll position , so if you are scrolled to the top of the document already it will work as expected, but any further scrolling will cause trouble, since the document has been moved. You need to take into account the current scroll position as well by adding it in to the final scroll value so it doesn't get 'lost'.

Here is an example with both issues addressed:

function customScrollTo (section) {

     $('#wrapper').animate({
         scrollTop: $("#wrapper div[id='" + section + "']").position().top + $("#wrapper").scrollTop()
     }, 200);
 };

Use this:

function customScrollTo (sectionId) {
    var $wrapper = $('#wrapper'),
        $section = $('#' + sectionId);
     $wrapper.animate({
         scrollTop: $wrapper.scrollTop() + $section.position().top
     }, 200);
 }

The .offset() function gets the coordinates relative to the document, whereas the .position() function gets the coordinates relative to the parent. But the .position().top value changes as the element is scrolled. Adding the parent's .scrollTop() value can adjust for that.

jsfiddle

Try this, I have modified your markup as well. See this DEMO

$('#index ul').on('click', 'a', function(e) {
 var section = $(this).prop('href');
 section = section.split('#')[1];
 var top = $("#" + section)[0].offsetTop;

 $('#wrapper').stop().animate({
     scrollTop: top
 }, 200);
 return false;
 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM