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


159

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

scrollTo插件可以做到这一点,但是如果没有真正了解它的源代码,就很难理解。我不想使用这个插件。

比方说,我有一个功能,需要2元$parentDiv$innerListItem,既不$innerListItem.offset().top也不$innerListItem.positon().top让我对$ parentDiv正确scrollTop的。


由于您的更新,删除了我的答案。但请相信我,面前有同样的态度,有很多与位置和利润等浏览器的怪癖......插件是一个更简单的路线,耗时更少,只有3K GZip压缩。
尼克·克雷弗

1
仍然使用scrollTo插件。不难 $("#container").scrollTo(target, duration, options)。目标只是一个目标#anchor。做完了
Ryan McGeary'2

似乎应该没有其他插件就可以做到这一点。明天生病开始阅读源代码
mkoryak 2010年

5
@mkoryak-知识已经存在,但是当您解释浏览器的古怪之处时,您基本上会得到... .scrollTo插件,那么为什么要一直重新发明轮子呢?
尼克·克雷弗

1
恕我直言,您可能最终会从.scrollTo 今天获得所需的确切子集。但是在几个月的时间里,虽然.scrollTo已更新为IE9,FF4和Chrome 6,但必须重新开始... 3k似乎很便宜,可以避免这种情况。
Wim

Answers:


236

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

152

这是我自己的插件(会将元素放在列表的顶部。专门用于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)中进行了测试。

如果要滚动整个页面,请检查此问题


什么是elem?? 你根本不解释。
vsync

如果将fn.scrollTo中的$替换为jQuery,则会获得更好的里程/无冲突
Barry Carlyon

这样做有很大的缺陷,您无法控制范围:$(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem, $(this)).offset().top);-问候
卢克·斯诺登,2015年

1
如果要在页面和元素之间保留一些顶部空白(在某些情况下可能看起来更好),请减去10px,例如:$(this).scrollTop() - $(this).offset().top + $(elem).offset().top - 10
lepe

如果Firefox和Chrome(或其他浏览器)之间的位置有所不同,请检查您的html代码(请参阅此错误报告
lepe 2016年

34

我已经调整了Glenn Moss的答案,以说明以下事实:溢出div可能不在页面顶部。

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

我在带有响应模板的google maps应用程序上使用了它。分辨率> 800px时,列表位于地图的左侧。分辨率<800时,列表在地图下方。


6

上面的答案会将内部元素放置在溢出元素的顶部,即使它在溢出元素内部也是如此。我不希望这样,所以我对其进行了修改,以在元素处于可见状态时不更改滚动位置。

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


1

我写这两个函数使我的生活更轻松:

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

elem.offset().top从屏幕顶部开始计算。我希望从父元素进行计算。我怎么做 ?
桑托什

0

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

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

我这样称呼它

$("#basketListGridHolder").scrollTo('tr[data-uid="' + basketID + '"]');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.