Reputation: 13086
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:
Upvotes: 2
Views: 604
Reputation: 1547
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;
});
Upvotes: 0
Reputation: 21482
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.
Upvotes: 4
Reputation: 6218
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);
};
Upvotes: 5