如何检查滚动条是否可见?

327

能否检查一个div的overflow:auto?

例如:

HTML

<div id="my_div" style="width: 100px; height:100px; overflow:auto;" class="my_class"> 
  * content
</div>

JQUERY

$('.my_class').live('hover', function (event)
{
    if (event.type == 'mouseenter')
    {
         if( ...  if scrollbar visible ? ... )
         {
            alert('true'):
         }
         else
         {
            alert('false'):
         }
    }

});
有时候内容很短(没有滚动条),有时候很长(滚动条可见)。
21个回答

416

这是一个小插件。

(function($) {
    $.fn.hasScrollBar = function() {
        return this.get(0).scrollHeight > this.height();
    }
})(jQuery);

像这样使用它:

$('#my_div1').hasScrollBar(); // returns true if there's a `vertical` scrollbar, false otherwise..

本代码已在Firefox、Chrome和IE6、7、8中测试过可正常工作

但在使用body标签选择器时存在问题

演示


编辑

我发现当你有水平滚动条引起垂直滚动条出现时,此函数不起作用...

我找到另一个解决方案... 使用clientHeight

return this.get(0).scrollHeight > this.get(0).clientHeight;

26
如果您有填充,则需要使用 > this.innerHeight();。http://jsfiddle.net/p3FFL/210/ - jcubic
2
如果水平滚动条也存在,则这会出现问题,即使垂直滚动条存在,直到高度被水平滚动条高度缩小,这也会返回false。 - Ally
13
请注意,在Mac上,滚动条浮在内容上方,并在不使用时消失。在Windows上,它始终可见并占用水平空间。因此,仅仅因为内容可以滚动(这个函数能检测到),并不意味着滚动条一定存在。 - Andrew
2
(function($) { $.fn.hasScrollBar = function() { return this.get(0).scrollWidth > this.width); } })(jQuery); 这段代码适用于水平溢出。非常适合在iframe中检查网站的移动响应性。 - Alexander Nicholas Popa
2
scrollHeight > clientHeight,这适用于所有情况,包括填充和边框。 - Dee
显示剩余12条评论

114
你可以使用 Element.scrollHeight 属性和 Element.clientHeight 属性的组合来实现这一点。
根据 MDN 上的说明: > `Element.scrollHeight` 只读属性是元素内容的高度,包括因溢出而未在屏幕上显示的内容。滚动高度等于元素在视口内适合所有内容所需的最小 `clientHeight`,不使用垂直滚动条。它包括元素的填充但不包括其边距。
以及: > `Element.clientHeight` 只读属性以像素为单位返回元素的内部高度,包括填充但不包括水平滚动条高度、边框或外边距。 > `clientHeight` 可以通过计算 CSS 高度 + CSS 填充 - 水平滚动条的高度(如果存在)来得到。
因此,如果滚动高度大于客户端高度,则元素将显示滚动条,所以你的问题的答案是:
function scrollbarVisible(element) {
  return element.scrollHeight > element.clientHeight;
}

2
示例:https://github.com/twbs/bootstrap/blob/master/js/modal.js#L242,加上 MDN 的引用和解释再加一分! - lowtechsun
在 Chrome 中,如果内容有边框,则其不包括在 scrollHeight 中。 - A.T.
23
因为没有抄袭框架或库,所以给你点赞。 - John
2
小心 - 这会导致重新布局,从而影响性能。https://gist.github.com/paulirish/5d52fb081b3570c81e3a - Todd Sjolander
1
每次元素直接调整大小或其子元素调整大小(可能也会影响它)时,您都需要运行此函数。如果没有提到这些内容,这个答案不到一半完整。 - vsync

65

也许有一个更简单的解决方案。

if ($(document).height() > $(window).height()) {
    // scrollbar
}

在使用JQuery .ready()检查DOM是否准备好后,这个答案对我有用。 - Simple Sandman
12
假设滚动条位于窗口而非 div 元素上。建议更改引用以提供以下建议:"If you only need to test the scrollbar on the main window, you could try:"(如果您只需要测试主窗口上的滚动条,可以尝试:) - justdan23
谢谢,我使用这个答案来让我的页脚在文档高度小于窗口时位置变为绝对定位。 - Tarik Hacialiogullari

45

我应该修改一下Reigel所说的话:

(function($) {
    $.fn.hasScrollBar = function() {
        return this[0] ? this[0].scrollHeight > this.innerHeight() : false;
    }
})(jQuery);

innerHeight计算控件的高度以及其上下内边距。


返回(this.get(0))?this.get(0).scrollHeight> this.innerHeight():false; - commonpike
3
我认为这应该被指定为正确答案。在FF35、IE11和Chrome39上都可以使用。 - LucasBr
它没有检查“溢出”值,以确保当滚动高度达到该条件时会出现滚动条。 - B T
1
@BT 但是如果我在CSS中将溢出设置为自动,那么我就不需要这个额外的检查了吗?它会比较大小,这就足够了吗? - Andrew
一个只适用于你自己的答案并不是一个真正的答案。你怎么知道别人在他们的CSS中有什么?你的答案没有提到这个限制。如果有人不能直接使用你的答案,那么它就不是一个好的答案。 - B T

30
这进一步解释了@Reigel的答案。它将返回水平或垂直滚动条的答案。
(function($) {
    $.fn.hasScrollBar = function() {
        var e = this.get(0);
        return {
            vertical: e.scrollHeight > e.clientHeight,
            horizontal: e.scrollWidth > e.clientWidth
        };
    }
})(jQuery);

例子:

element.hasScrollBar()             // Returns { vertical: true/false, horizontal: true/false }
element.hasScrollBar().vertical    // Returns true/false
element.hasScrollBar().horizontal  // Returns true/false

1
无法通过检查<body>上的垂直条来工作,因为scrollHeight将始终等于clientHeight,当元素使用overflow:hidden时也会返回无效结果。 - L4marr

11

9

我为jQuery创建了一个新的自定义:pseudo选择器,用于测试元素是否具有以下CSS属性之一:

  1. overflow: [scroll|auto]
  2. overflow-x: [scroll|auto]
  3. overflow-y: [scroll|auto]

我想找到另一个元素的最近滚动父级,因此我还编写了另一个小型的jQuery插件来查找具有溢出的最近父级。

这个解决方案可能不是性能最佳的,但它似乎起作用。我与$.scrollTo插件一起使用它。有时我需要知道一个元素是否在另一个可滚动容器内。在这种情况下,我希望滚动父可滚动元素而不是窗口。

我应该将这个插件封装成一个单一的插件,并将伪选择器作为插件的一部分添加,并公开一个“closest”方法来查找最近(父)可滚动容器。

无论如何……这就是它。

$.isScrollable jQuery插件:

$.fn.isScrollable = function(){
    var elem = $(this);
    return (
    elem.css('overflow') == 'scroll'
        || elem.css('overflow') == 'auto'
        || elem.css('overflow-x') == 'scroll'
        || elem.css('overflow-x') == 'auto'
        || elem.css('overflow-y') == 'scroll'
        || elem.css('overflow-y') == 'auto'
    );
};

$(':scrollable') jQuery 伪选择器:

$.expr[":"].scrollable = function(a) {
    var elem = $(a);
    return elem.isScrollable();
};

$.scrollableparent() jQuery plugin:

$.fn.scrollableparent = function(){
    return $(this).closest(':scrollable') || $(window); //default to $('html') instead?
};

实现非常简单

//does a specific element have overflow scroll?
var somedivIsScrollable = $(this).isScrollable();
//use :scrollable psuedo selector to find a collection of child scrollable elements
var scrollableChildren = $(this).find(':scrollable');
//use $.scrollableparent to find closest scrollable container
var scrollableparent = $(this).scrollableparent();

更新: 我发现Robert Koritnik已经提出了一个更强大的:scrollable伪选择器,可以识别可滚动容器的可滚动轴和高度,作为他的$.scrollintoview() jQuery插件的一部分。滚动到视图插件

这是他花哨的伪选择器(props):

    $.extend($.expr[":"], {

    scrollable: function (element, index, meta, stack) {

        var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()] || converter.both;

        var styles = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(element, null) : element.currentStyle);

        var overflow = {

            x: scrollValue[styles.overflowX.toLowerCase()] || false,

            y: scrollValue[styles.overflowY.toLowerCase()] || false,

            isRoot: rootrx.test(element.nodeName)

        };



        // check if completely unscrollable (exclude HTML element because it's special)

        if (!overflow.x && !overflow.y && !overflow.isRoot)

        {

            return false;

        }



        var size = {

            height: {

                scroll: element.scrollHeight,

                client: element.clientHeight

            },

            width: {

                scroll: element.scrollWidth,

                client: element.clientWidth

            },

            // check overflow.x/y because iPad (and possibly other tablets) don't dislay scrollbars

            scrollableX: function () {

                return (overflow.x || overflow.isRoot) && this.width.scroll > this.width.client;

            },

            scrollableY: function () {

                return (overflow.y || overflow.isRoot) && this.height.scroll > this.height.client;

            }

        };

        return direction.y && size.scrollableY() || direction.x && size.scrollableX();

    }

});

9

(scrollWidth/Height - clientWidth/Height) 是判断是否存在滚动条的一个好指标,但在许多情况下它会给出“误报”的答案。如果需要精确判断,建议使用以下函数。不要试图猜测元素是否可滚动,你可以尝试滚动它...

function isScrollable( el ){
  var y1 = el.scrollTop;
  el.scrollTop  += 1;
  var y2 = el.scrollTop;
  el.scrollTop  -= 1;
  var y3 = el.scrollTop;
  el.scrollTop   = y1;
  var x1 = el.scrollLeft;
  el.scrollLeft += 1;
  var x2 = el.scrollLeft;
  el.scrollLeft -= 1;
  var x3 = el.scrollLeft;
  el.scrollLeft  = x1;
  return {
    horizontallyScrollable: x1 !== x2 || x2 !== x3,
    verticallyScrollable: y1 !== y2 || y2 !== y3
  }
}
function check( id ){
  alert( JSON.stringify( isScrollable( document.getElementById( id ))));
}
#outer1, #outer2, #outer3 {
  background-color: pink;
  overflow: auto;
  float: left;
}
#inner {
  width:  150px;
  height: 150px;
}
button {  margin: 2em 0 0 1em; }
<div id="outer1" style="width: 100px; height: 100px;">
  <div id="inner">
    <button onclick="check('outer1')">check if<br>scrollable</button>
  </div>
</div>
<div id="outer2" style="width: 200px; height: 100px;">
  <div id="inner">
    <button onclick="check('outer2')">check if<br>scrollable</button>
  </div>
</div>
<div id="outer3" style="width: 100px; height: 180px;">
  <div id="inner">
    <button onclick="check('outer3')">check if<br>scrollable</button>
  </div>
</div>


1
在什么情况下会出现误报? - GaloisGirl
有没有办法在执行这些操作时阻止滚动事件? - AshD

6

哎呀,这里的每个答案都不完整,请不要在stackoverflow的回答中再使用jquery。如果您想了解有关jquery的信息,请查看jquery的文档。

这是一个通用的纯JavaScript函数,可完全测试元素是否具有滚动条:

// dimension - Either 'y' or 'x'
// computedStyles - (Optional) Pass in the domNodes computed styles if you already have it (since I hear its somewhat expensive)
function hasScrollBars(domNode, dimension, computedStyles) {
    dimension = dimension.toUpperCase()
    if(dimension === 'Y') {
        var length = 'Height'
    } else {
        var length = 'Width'
    }

    var scrollLength = 'scroll'+length
    var clientLength = 'client'+length
    var overflowDimension = 'overflow'+dimension

    var hasVScroll = domNode[scrollLength] > domNode[clientLength]


    // Check the overflow and overflowY properties for "auto" and "visible" values
    var cStyle = computedStyles || getComputedStyle(domNode)
    return hasVScroll && (cStyle[overflowDimension] == "visible"
                         || cStyle[overflowDimension] == "auto"
                         )
          || cStyle[overflowDimension] == "scroll"
}

5
为什么要在标记为jquery的问题中避免使用jquery?请添加你提到的jquery文档部分的链接。 - kpull1
8
太多人在每个JavaScript问题上都加了jQuery标签。这个问题与jQuery没有任何关系。jQuery文档中也没有任何部分提供答案,因为jQuery不会做这个事情,也不应该这样做。 - B T

5

以上第一种解决方案仅适用于IE浏览器,第二种解决方案仅适用于FF浏览器。

两种函数的组合可以在两种浏览器中都使用:

//Firefox Only!!
if ($(document).height() > $(window).height()) {
    // has scrollbar
    $("#mtc").addClass("AdjustOverflowWidth");
    alert('scrollbar present - Firefox');
} else {
    $("#mtc").removeClass("AdjustOverflowWidth");
}

//Internet Explorer Only!!
(function($) {
    $.fn.hasScrollBar = function() {
        return this.get(0).scrollHeight > this.innerHeight();
    }
})(jQuery);
if ($('#monitorWidth1').hasScrollBar()) {
    // has scrollbar
    $("#mtc").addClass("AdjustOverflowWidth");
    alert('scrollbar present - Internet Exploder');
} else {
    $("#mtc").removeClass("AdjustOverflowWidth");
}​
  • 将其包装在文档准备好的函数中
  • monitorWidth1:设置overflow为auto的div
  • mtc:位于monitorWidth1内部的容器div
  • AdjustOverflowWidth:当滚动条激活时应用于#mtc div的css类 *使用alert测试跨浏览器,然后注释掉最终生产代码。

希望对你有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接