【问题标题】: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 的代码也极大地帮助了我解决问题。它为我指明了正确的方向。

【问题讨论】:

    标签: javascript dom scrollbar overflow


    【解决方案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(第二张图片)

    您需要检查:

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

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

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

    希望这会有所帮助!

    【讨论】:

      【解决方案6】:

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

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

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

      【讨论】:

      【解决方案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 会,所以你得到错误的计算。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-10-24
          • 1970-01-01
          • 2013-09-28
          • 2010-10-03
          • 2018-02-01
          • 2011-10-26
          • 2014-09-08
          • 1970-01-01
          相关资源
          最近更新 更多