I have 20 list items inside of a div that can only show 5 at a time. What is a good way to scroll to item #10, and then item #20? I know the height of all the items.
The scrollTo
plugin does this, but its source is not super easy to understand without really getting into it. I don't want to use this plugin.
Let's say I have a function that takes 2 elements $parentDiv
, $innerListItem
, neither $innerListItem.offset().top
nor $innerListItem.positon().top
gives me the correct scrollTop for $parentDiv.
The $innerListItem.position().top
is actually relative to the .scrollTop()
of its first positioned ancestor. So the way to calculate the correct $parentDiv.scrollTop()
value is to begin by making sure that $parentDiv
is positioned. If it doesn't already have an explicit position
, use position: relative
. The elements $innerListItem
and all its ancestors up to $parentDiv
need to have no explicit position. Now you can scroll to the $innerListItem
with:
// Scroll to the top
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top);
// Scroll to the center
$parentDiv.scrollTop($parentDiv.scrollTop() + $innerListItem.position().top
- $parentDiv.height()/2 + $innerListItem.height()/2);
This is my own plugin (will position the element in top of the the list. Specially for overflow-y : auto
. May not work with overflow-x
!):
NOTE: elem
is the HTML selector of an element which the page will be scrolled to. Anything supported by jQuery, like: #myid
, div.myclass
, $(jquery object)
, [dom object], etc.
jQuery.fn.scrollTo = function(elem, speed) {
$(this).animate({
scrollTop: $(this).scrollTop() - $(this).offset().top + $(elem).offset().top
}, speed == undefined ? 1000 : speed);
return this;
};
If you don't need it to be animated, then use:
jQuery.fn.scrollTo = function(elem) {
$(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top);
return this;
};
How to use:
$("#overflow_div").scrollTo("#innerItem");
$("#overflow_div").scrollTo("#innerItem", 2000); //custom animation speed
Note: #innerItem
can be anywhere inside #overflow_div
. It doesn't really have to be a direct child.
Tested in Firefox (23) and Chrome (28).
If you want to scroll the whole page, check this question.
I've adjusted Glenn Moss' answer to account for the fact that overflow div might not be at the top of the page.
parentDiv.scrollTop(parentDiv.scrollTop() + (innerListItem.position().top - parentDiv.position().top) - (parentDiv.height()/2) + (innerListItem.height()/2) )
I was using this on a google maps application with a responsive template. On resolution > 800px, the list was on the left side of the map. On resolution < 800 the list was below the map.
The above answers will position the inner element at the top of the overflow element even if it's in view inside the overflow element. I didn't want that so I modified it to not change the scroll position if the element is in view.
jQuery.fn.scrollTo = function(elem, speed) {
var $this = jQuery(this);
var $this_top = $this.offset().top;
var $this_bottom = $this_top + $this.height();
var $elem = jQuery(elem);
var $elem_top = $elem.offset().top;
var $elem_bottom = $elem_top + $elem.height();
if ($elem_top > $this_top && $elem_bottom < $this_bottom) {
// in view so don't do anything
return;
}
var new_scroll_top;
if ($elem_top < $this_top) {
new_scroll_top = {scrollTop: $this.scrollTop() - $this_top + $elem_top};
} else {
new_scroll_top = {scrollTop: $elem_bottom - $this_bottom + $this.scrollTop()};
}
$this.animate(new_scroll_top, speed === undefined ? 100 : speed);
return this;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With