如何滚动到溢出 Div 中的元素?

我在一个 div 中有20个列表项,每次只能显示5个。什么是一个好方法滚动到项目 # 10,然后项目 # 20?我知道所有物品的高度。

虽然 scrollTo插件可以做到这一点,但是它的源代码并不是非常容易理解,如果不能真正了解它的话

假设我有一个包含2个元素 $parentDiv$innerListItem的函数,$innerListItem.offset().top$innerListItem.positon().top都没有给出 $ParentDiv 的正确 scrollTop。

152902 次浏览

$innerListItem.position().top实际上是相对于其第一个定位的祖先的 .scrollTop()。因此,计算正确的 $parentDiv.scrollTop()值的方法是从确保 $parentDiv的位置开始。如果它还没有显式的 position,那么使用 position: relative。元素 $innerListItem及其到 $parentDiv的所有祖先都不需要有显式的位置。现在你可以滚动到 $innerListItem:

// 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);

我调整了 Glenn Moss 的回答,以考虑溢出 div 可能不在页面顶部这一事实。

parentDiv.scrollTop(parentDiv.scrollTop() + (innerListItem.position().top - parentDiv.position().top) - (parentDiv.height()/2) + (innerListItem.height()/2)  )

我在一个带有响应模板的谷歌地图应用程序中使用了这个。在分辨率 > 800px 时,该列表位于地图的左侧。在分辨率 < 800的情况下,名单在地图下面。

这是我自己的插件(将元素放置在列表的顶部。特别是 overflow-y : auto。可能无法与 overflow-x一起工作!):

注意 : elem是页面将滚动到的元素的 HTML 选择器。JQuery 支持的任何内容,如: #myiddiv.myclass$(jquery object)、[ dom 对象]等。

jQuery.fn.scrollTo = function(elem, speed) {
$(this).animate({
scrollTop:  $(this).scrollTop() - $(this).offset().top + $(elem).offset().top
}, speed == undefined ? 1000 : speed);
return this;
};

如果你不需要动画,那么使用:

jQuery.fn.scrollTo = function(elem) {
$(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top);
return this;
};

使用方法:

$("#overflow_div").scrollTo("#innerItem");
$("#overflow_div").scrollTo("#innerItem", 2000); //custom animation speed

注意: #innerItem可以在 #overflow_div中的任何位置,它不一定是直接子元素。

在 Firefox (23)和 Chrome (28)中测试。

如果要滚动整个页面,请选中 这个问题

在玩了很长时间之后,我想到了这个主意:

    jQuery.fn.scrollTo = function (elem) {
var b = $(elem);
this.scrollTop(b.position().top + b.height() - this.height());
};

我这样称呼它

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');

上面的答案将把内部元素放置在溢出元素的顶部,即使它在溢出元素内部的视图中。我不希望这样,所以我修改它不改变滚动位置,如果元素在视图中。

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;
};

我写这两个函数是为了让我的生活更轻松:

function scrollToTop(elem, parent, speed) {
var scrollOffset = parent.scrollTop() + elem.offset().top;
parent.animate({scrollTop:scrollOffset}, speed);
// parent.scrollTop(scrollOffset, speed);
}


function scrollToCenter(elem, parent, speed) {
var elOffset = elem.offset().top;
var elHeight = elem.height();
var parentViewTop = parent.offset().top;
var parentHeight = parent.innerHeight();
var offset;


if (elHeight >= parentHeight) {
offset = elOffset;
} else {
margin = (parentHeight - elHeight)/2;
offset = elOffset - margin;
}


var scrollOffset = parent.scrollTop() + offset - parentViewTop;


parent.animate({scrollTop:scrollOffset}, speed);
// parent.scrollTop(scrollOffset, speed);
}

使用它们:

scrollToTop($innerListItem, $parentDiv, 200);
// or
scrollToCenter($innerListItem, $parentDiv, 200);

接受的答案只适用于可滚动元素的直接子元素,而其他答案不会将子元素放在可滚动元素的中心。

示例 HTML:

<div class="scrollable-box">
<div class="row">
<div class="scrollable-item">
Child 1
</div>
<div class="scrollable-item">
Child 2
</div>
<div class="scrollable-item">
Child 3
</div>
<div class="scrollable-item">
Child 4
</div>
<div class="scrollable-item">
Child 5
</div>
<div class="scrollable-item">
Child 6
</div>
<div class="scrollable-item">
Child 7
</div>
<div class="scrollable-item">
Child 8
</div>
<div class="scrollable-item">
Child 9
</div>
<div class="scrollable-item">
Child 10
</div>
<div class="scrollable-item">
Child 11
</div>
<div class="scrollable-item">
Child 12
</div>
<div class="scrollable-item">
Child 13
</div>
<div class="scrollable-item">
Child 14
</div>
<div class="scrollable-item">
Child 15
</div>
<div class="scrollable-item">
Child 16
</div>
</div>
</div>


<style>
.scrollable-box {
width: 800px;
height: 150px;
overflow-x: hidden;
overflow-y: scroll;
border: 1px solid #444;
}
.scrollable-item {
font-size: 20px;
padding: 10px;
text-align: center;
}
</style>

构建一个小的 jQuery 插件:

$.fn.scrollDivToElement = function(childSel) {
if (! this.length) return this;


return this.each(function() {
let parentEl = $(this);
let childEl = parentEl.find(childSel);


if (childEl.length > 0) {
parentEl.scrollTop(
parentEl.scrollTop() - parentEl.offset().top + childEl.offset().top - (parentEl.outerHeight() / 2) + (childEl.outerHeight() / 2)
);
}
});
};

用法:

$('.scrollable-box').scrollDivToElement('.scrollable-item:eq(12)');

说明:

  1. parentEl.scrollTop(...)设置滚动条的当前垂直位置。

  2. parentEl.scrollTop()获取滚动条的当前垂直位置。

  3. parentEl.offset().top获取 父母相对于文档的当前坐标。

  4. childEl.offset().top获取 孩子相对于文档的当前坐标。

  5. parentEl.outerHeight() / 2将子元素的外部高度分成两半(因为我们希望它居中)。

  6. 使用时:

$(parent).scrollDivToElement(child);

家长是可滚动的 div,它可以是 DOM 元素的字符串或 jQuery 对象。
孩子是您想要滚动到的任何子元素,它可以是 DOM 元素的字符串或 jQuery 对象。

代码演示