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

时间:2010-02-27 02:28:22

标签: jquery

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

scrollTo插件可以做到这一点,但是如果没有真正进入它,其源代码就不容易理解。 我不想使用此插件。

假设我有一个函数需要2个元素$parentDiv$innerListItem$innerListItem.offset().top$innerListItem.positon().top都没有为$ parentDiv提供正确的scrollTop。

7 个答案:

答案 0 :(得分:222)

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

答案 1 :(得分:138)

这是我自己的插件(将元素置于列表顶部。特别适用于overflow-y : auto。可能不适用于overflow-x!):

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

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)中测试过。

如果您想滚动整个页面,请检查this question

答案 2 :(得分:31)

我已经调整了Glenn Moss的回答,说明溢出div可能不在页面顶部。

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

我在带有响应式模板的Google地图应用程序中使用此功能。关于分辨率> 800px,列表位于地图的左侧。关于决议< 800列表在地图下方。

答案 3 :(得分:5)

上面的答案将内部元素定位在溢出元素的顶部,即使它在溢出元素内部也是如此。我不想这样,所以如果元素在视图中,我将其修改为不更改滚动位置。

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

答案 4 :(得分:2)

已接受的答案仅适用于可滚动元素的直接子元素,而其他答案并未将其子元素置于可滚动元素的中心。

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获取 parentEl 相对于文档的当前坐标。

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

  5. parentEl.outerHeight() / 2获得子元素的外部高度的一半(因为我们希望它居中)。

  6. 使用时:

$(parent).scrollDivToElement(child);

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

Codepen demo

答案 5 :(得分:0)

在玩了很长时间之后,这就是我想出来的:

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

我称之为

{{1}}

答案 6 :(得分:0)

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

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