检查HTML元素是否具有滚动条


113

检查元素是否具有滚动条的最快方法是什么?

当然,一件事是检查element是否大于其视口,这可以通过检查以下两个值来轻松完成:

el.scrollHeight > el.offsetHeight || el.scrollWidth > el.offsetWidth

但这并不意味着它也具有滚动条(因此它实际上可以被人类滚动)。

如何在1个跨浏览器和2个 javascript中检查滚动条(如无jQuery)?

仅使用Javascript,因为我需要尽可能小的开销,因为我想编写一个非常快速的jQuery选择器过滤器

// check for specific scrollbars
$(":scrollable(x/y/both)")

// check for ANY scrollbar
$(":scrollable")

我想我必须检查overflow样式设置,但是如何以跨浏览器的方式进行呢?

附加编辑

不仅是overflow样式设置。检查元素是否具有滚动条并不是看起来那么简单。我上面写的第一个公式在元素没有边框的时候很好用,但是当元素没有边框时(特别是当边框的宽度很大时),offset尺寸可以大于scroll尺寸,但是元素仍然可以滚动。实际上,我们必须从offset尺寸中减去边框以获得元素的实际可滚动视口,并将其与scroll尺寸进行比较。

备查

:scrollablejQuery选择器过滤器包含在我的.scrollintoview()jQuery插件中。如果有人需要,可以在我的博客文章中找到完整的代码。即使没有提供实际的解决方案,Soumya的代码也极大地帮助我解决了问题。它为我指明了正确的方向。

Answers:


118

几周前我在某个地方发现了这个。它为我工作。

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = div.scrollWidth > div.clientWidth;
var hasVerticalScrollbar = div.scrollHeight > div.clientHeight;

/* you'll get true/false */

12
您显然有一个简化的示例。如果您的容器overflow:hidden放在上面怎么办?会有多余的内容,但仍然无法滚动。到目前为止,问题并不像看起来那样简单。
罗伯特·科里特尼克

7
这可能不是公认的解决方案,但对我有用。我不确定如果隐藏它为什么还要滚动它。
vol7ron 2011年

这可能不是公认的解决方案,但对我有用。罗伯特,对于这些情况,您是否也无法获取css溢出属性来测试这些情况(例如div.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden'))?
vol7ron 2011年

7
在许多情况下,这将失败。如果您的元素有溢出:宽度:200px;并且有一个宽度为500px的子元素,您的元素没有滚动条,但scrollWidth为500px,clientWidth为200px。
Joseph Lennox

1
如果可见或隐藏了溢出,则通常没有滚动条。
Hubert Grzeskowiak

16

尝试:

对于垂直滚动条

el.scrollHeight> el.clientHeight

对于水平滚动条

el.scrollWidth> el.clientWidth

我知道这至少适用于IE8和Firefox 3.6+。


2
我指出是的,这告诉我某个元素比看起来大,但这并不意味着它显示滚动条。它也可以拥有overflow:hidden并且将不再可滚动。
罗伯特·科里特尼克

1
而且,使用clientHeight / clientWidth值进行检查不会产生良好的结果,因为元素也可以具有边框,而边框不包含在此度量中。检查我的公式。它比您的效果更好。
罗伯特·科里特尼克

关于使用offsetHeight / offsetWidth而不是clientHeight / clientWidth检查滚动条,这是正确的。感谢您指出了这一点。
加里

@RobertKoritnik-因此,只需检查该特定元素overflow:hidden上是否存在……在我看来,这仍然是正确的答案,因为它是最简单的。
vsync 2014年

14

这似乎有点(或有点)怪异,但您可以测试scrollTopscrollLeft属性。

如果它们大于0,则说明存在滚动条。如果它们是0,则将它们设置为1,然后再次对其进行测试,以查看结果是否为1。然后将它们重新设置为0。

示例: http //jsfiddle.net/MxpR6/1/

function hasScroll(el, direction) {
    direction = (direction === 'vertical') ? 'scrollTop' : 'scrollLeft';
    var result = !! el[direction];

    if (!result) {
        el[direction] = 1;
        result = !!el[direction];
        el[direction] = 0;
    }
    return result;
}

alert('vertical? ' + hasScroll(document.body, 'vertical'));
alert('horizontal? ' + hasScroll(document.body, 'horizontal'));

我相信IE有一个不同的属性,因此我将在一分钟内进行更新。

编辑:似乎IE可能支持此属性。(我现在无法测试IE。)

http://msdn.microsoft.com/zh-CN/library/ms534618(VS.85).aspx


如果将offsetHeight和进行比较,则检查滚动条要容易得多clientHeight。如果存在滚动条,则后者总是比滚动条的大小小。
罗伯特·科里特尼克

@Robert:不确定是否更容易,但是我知道它是如何工作的。然后,我假设某个元素是否具有overflow:scroll,无论是否启用滚动条,您都希望将其报告为可滚动的。当然,如果有附加的onscroll事件,我的解决方案可能会出现问题。
user113716 2011年

并不是的。如果您检查我的jQuery插件,我必须找到实际的可滚动祖先,否则我无法将元素滚动到视图中。
罗伯特·科里特尼克

8
@RobertKoritnik不正确;某些浏览器的滚动条可能不会减小宽度。例如在OS X上。或触摸设备。
daniel.gindi 2014年

1
总是返回false
Fatih Erol

14

这是另一个解决方案:

正如一些人指出的那样,仅比较offsetHeight和scrollHeight是不够的,因为它们在具有隐藏的溢出等内容的元素上有所不同,等等,这些元素仍然没有滚动条。所以在这里我还要检查元素的计算样式是否为滚动或自动溢出:

var isScrollable = function(node) {
  var overflowY = window.getComputedStyle(node)['overflow-y'];
  var overflowX = window.getComputedStyle(node)['overflow-x'];
  return {
    vertical: (overflowY === 'scroll' || overflowY === 'auto') && node.scrollHeight > node.clientHeight,
    horizontal: (overflowX === 'scroll' || overflowX === 'auto') && node.scrollWidth > node.clientWidth,
  };
}

如果overflow*scroll,总是会有一个滚动条,所以我想你想vertical: overflowY === 'scroll' || overflowY === 'auto' && node.scrollHeight > node.clientHeight,等(即去掉括号所以scroll*VS client*仅测试时overflow*auto)。否则,这似乎是最正确的解决方案。
杰克

@Jake如果scrollHeight <clientHeight滚动溢出,则滚动条将存在,但将被禁用(即,元素不可滚动)。因此,我认为这取决于应用程序。您的修改对您有效,您只想检查滚动条,而与状态无关。对我来说,当我想到这一点时,我正在寻求为组件实现自动滚动,因此在这种情况下禁用滚动条是没有用的。这个问题似乎也是如此(它需要“被人类滚动”)
lotif

6

我可能聚会晚了一点,但是...

我相信您可以使用e.offsetWidth与e.clientWidth来检测滚动条。偏移宽度包括边框和滚动条,填充和宽度。客户宽度包括填充和宽度。请参见:

https://developer.mozilla.org/en/DOM/element.offsetWidth(第二张图片) https://developer.mozilla.org/en/DOM/element.clientWidth(第二张图片)

您需要检查:

  1. 元素是否使用计算/级联/当前样式将溢出设置为自动/滚动(包括overflowX / Y)。
  2. 如果元素确实具有设置为自动/滚动的溢出。建立offsetWidth和clientWidth。
  3. 如果clientWidth小于offsetWidth-右边界(通过计算/级联/当前样式再次找到),则说明您具有滚动条。

对垂直方向(偏移量/ clientHeight)执行相同的操作。

IE7报告某些元素的clientHeight为0(我没有检查原因),因此,您始终需要进行第一次溢出检查。

希望这可以帮助!


3

检查滚动条是否存在几个问题,其中之一是在Mac中您没有任何可见的滚动条,因此上述所有解决方案都无法为您提供准确的答案。

因此,由于浏览器的渲染不是很频繁,因此您可以通过更改滚动来检查是否具有滚动,然后将其重新设置为:

const hasScrollBar = (element) => {
  const {scrollTop} = element;

  if(scrollTop > 0) {
    return true;
  }

  element.scrollTop += 10;

  if(scrollTop === element.scrollTop) {
    return false;
  }

  // undoing the change
  element.scrollTop = scrollTop;
  return true;
};


1

只是在这里弄乱,因为上述解决方案都没有为我解决(到目前为止)。通过将Div的scrollheight与offsetHeight进行比较,我发现了一些成功

var oh = $('#wrapDiv').get(0).offsetHeight;
var sh = $('#wrapDiv').get(0).scrollHeight;

到目前为止,这似乎给了我一个准确的比较。有人知道这是否合法吗?


2
我想你想scrollHeight属性和clientHeight:stackoverflow.com/questions/4106538/...
丰富REMER

1

对于IE11(Internet Explorer 11),我必须将逻辑更改为:

// Subtract 3 (a small arbitrary number) to allow for IE reporting a difference of 1 when no scrollbar is present
var hasVerticalScrollbar = div.scrollHeight - 3 > div.clientHeight;

这是因为,当不存在滚动条时,IE报告的scrollHeight比clientHeight大1,但是当存在滚动条时,其约大9倍于clientHeight。


0

如果您需要了解整个网页上是否存在滚动条并且具有完整的浏览器支持,则可以使用以下命令:

const hasScrollbar = document.body.scrollHeight > window.innerHeight

使用window.innerHeight而不是使用非常重要,document.body.clientHeight因为在某些移动浏览器中,clientHeight不会获得地址栏的大小,而scrollHeight会得到,因此您将得到错误的计算。


-5

这些答案均不正确。您必须使用此:

var div = document.getElementById('container_div_id');

var hasHorizontalScrollbar = (div.offsetWidth > div.clientWidth);
var hasVerticalScrollbar = (div.offsetHeight > div.clientHeight);

它之所以被否决,是因为它是从6年前接受的答案中复制/粘贴的,您不需要括号就可以将某物转换为布尔值。
摩托车

-6

在其中添加100%宽的元素。然后将溢出设置为隐藏。如果元素的计算样式(来自jQ)发生更改,则父元素具有滚动条。

编辑:似乎您想要一个跨浏览器方法,如getComputedStyle。尝试:

function getCSS(_elem, _style)
{
    var computedStyle;
    if (typeof _elem.currentStyle != 'undefined')
        computedStyle = _elem.currentStyle;
    else
        computedStyle = document.defaultView.getComputedStyle(_elem, null);
    return computedStyle[_style];
}

1
如果我已经为此使用了jQuery,我宁愿去做$(el).css("overflow/overflowX/overflowY"),看看它是设置为auto还是scroll但我想避免使用jQuery。
罗伯特·科里特尼克

16
CSS样式不会告诉您元素是否具有滚动条。只有它是否可以有滚动条。也许找到确定内部元素宽度的跨浏览器方法?
Soumya

@ Soumya92:可滚动大小和实际大小之间的大小比较是微不足道的,我已经在上面写过了……现在,我需要检查的只是特定元素上的当前溢出设置。
罗伯特·科里特尼克

@ Soumya92:这正是我所需要的。通过使用合并,它也可以大大简化computedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null);
Robert Koritnik 2011年

还有一件事:这是如何跨浏览器的?这支持哪些浏览器?
罗伯特·科里特尼克
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.