检查 HTML 元素是不是有滚动条

Posted

技术标签:

【中文标题】检查 HTML 元素是不是有滚动条【英文标题】:Check whether HTML element has scrollbars检查 HTML 元素是否有滚动条 【发布时间】:2011-06-20 07:19:11 【问题描述】:

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

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

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

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

问题

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

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

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

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

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

其他编辑

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

供日后参考

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

【问题讨论】:

【参考方案1】:

在其中添加一个 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];

【讨论】:

如果我已经为此使用了 jQuery,我宁愿只做 $(el).css("overflow/overflowX/overflowY") 并查看它是设置为 auto 还是 scroll但我想避免使用 jQuery。 CSS 样式不会告诉你元素是否滚动条。只是它是否可以有滚动条。也许找到一种确定内部元素宽度的跨浏览器方法? @Soumya92:可滚动大小和实际大小之间的大小比较是微不足道的,我已经在上面写了...我现在需要检查的是特定元素上的当前溢出设置。 @Soumya92:这正是我所需要的。使用 coalesce computedStyle = el.currentStyle || document.defaultView.getComputedStyle(el, null); 也可以大大简化它 还有一件事:这是如何跨浏览器的?这个支持哪些浏览器?【参考方案2】:

试试:

垂直滚动条

el.scrollHeight > el.clientHeight

水平滚动条

el.scrollWidth > el.clientWidth

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

【讨论】:

我指出是的,这告诉我某个元素比看起来要大,但这并不意味着它会显示滚动条。它也可以有 overflow:hidden 并且它不再是可滚动的。 并且使用 clientHeight/clientWidth 值检查并不能给出好的结果,因为元素也可以有边框,这不包括在这个度量中。检查我的公式。它比你的效果更好。 使用 offsetHeight/offsetWidth 代替 clientHeight/clientWidth 检查滚动条是正确的。感谢您指出这一点。 @RobertKoritnik - 所以只需检查该特定元素上是否有overflow:hidden...在我看来这仍然是正确答案,因为它是最简单的。【参考方案3】:

这可能看起来(或)有点老套,但您可以测试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/en-us/library/ms534618(VS.85).aspx

【讨论】:

比较offsetHeightclientHeight 会更容易检查滚动条。当滚动条存在时,后者总是比滚动条小。 @Robert:不确定是否更容易,但我确实知道它是如何工作的。然后我假设如果一个元素有overflow:scroll,无论滚动条是否启用,你都希望它被报告为可滚动的。当然,如果附加了 onscroll 事件,我的解决方案可能会出现问题。 并非如此。如果您检查我的jQuery plugin,我必须找到实际的可滚动祖先,否则我无法将元素滚动到视图中。 @RobertKoritnik 不正确;某些浏览器可能具有不会减小宽度的滚动条。例如在 OS X 上。或触摸设备。 总是返回 false【参考方案4】:

几周前我在某个地方发现了这个。它对我有用。

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

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

/* you'll get true/false */

【讨论】:

你显然有一个简化的例子。如果您的容器上设置了overflow:hidden 怎么办?会有多余的内容,但它仍然不可滚动。问题远没有看起来那么简单。 这可能不是公认的解决方案,但它对我有用。我不知道如果它被隐藏了你为什么要滚动它。 这可能不是公认的解决方案,但它对我有用。罗伯特,对于这些情况,你不能也获取 css 溢出属性来测试这些情况(例如div.scrollHeight>div.clientHeight && !(div.style.overflow && div.style.overflow == 'hidden'))吗? 这在很多情况下都会失败。如果您的元素溢出:可见;宽度:200px;并且有一个宽度为 500px 的子元素,您的元素没有滚动条,但 scrollWidth 为 500px,clientWidth 为 200px。 如果溢出可见或隐藏,通常没有滚动条。【参考方案5】:

我参加聚会可能有点晚了,但是...

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

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

您需要检查:

    元素是否使用计算/级联/当前样式将溢出设置为自动/滚动(包括溢出X/Y)。 如果元素确实将溢出设置为自动/滚动。建立 offsetWidth 和 clientWidth。 如果 clientWidth 小于 offsetWidth - 右边框(通过计算/级联/当前样式再次找到),那么您知道您有一个滚动条。

对垂直(偏移量/客户端高度)执行相同操作。

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

希望这会有所帮助!

【讨论】:

【参考方案6】:

只是在这里搞乱,因为上述解决方案都没有为我解决(到目前为止)。 我发现将 Div 的滚动高度与其 offsetHeight 进行比较取得了一些成功

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

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

【讨论】:

我想你想要 scrollHeight 和 clientHeight:***.com/questions/4106538/…【参考方案7】:

这是另一个解决方案:

正如一些人指出的那样,仅比较 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*client* 仅经过测试当overflow*auto)。否则这似乎是最正确的解决方案。 @Jake 如果滚动溢出时 scrollHeight 【参考方案8】:

这些答案都不正确。你必须使用这个:

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

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

【讨论】:

这被否决了,因为它是从 6 年前接受的答案中复制/粘贴的,并且您不需要括号将某些东西变成布尔值。【参考方案9】:

对于 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

【讨论】:

【参考方案10】:

在检查滚动条是否存在的情况下存在几个问题,其中之一是在 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;
;

【讨论】:

+10 不是必须的,较低的值也应该起作用。 @sudazzle 问题是某些浏览器的工作方式与缩放相关。 +10 只是一个边距,但如果您不考虑缩放,那么即使使用 +1 或 +2 也可以。【参考方案11】:

如果您需要知道整个网页是否存在滚动条并且完整的浏览器支持,您可以使用:

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

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

【讨论】:

以上是关于检查 HTML 元素是不是有滚动条的主要内容,如果未能解决你的问题,请参考以下文章

网页右边怎么有2个滚动条,怎么去掉里面的滚动条呢?

Selenium WebDriver如何使滚动条滚动到最元素位置

Javascript禁止父元素滚动条滚动, pc移动端均有效

Selenium WebDriver如何使滚动条滚动到最元素位置

jquery获取滚动条高度和位置

Flexbox 溢出滚动条显示在正文而不是内部元素上