检测页面是否有垂直滚动条?

137

我只想要一些简单的JQ/JS代码来检查当前页面/窗口(而不是特定元素)是否有垂直滚动条。

谷歌搜索给出的结果似乎对于这个基本功能来说过于复杂了。

如何实现呢?

13个回答

104
$(document).ready(function() {
    // Check if body height is higher than window height :)
    if ($("body").height() > $(window).height()) {
        alert("Vertical Scrollbar! D:");
    }

    // Check if body width is higher than window width :)
    if ($("body").width() > $(window).width()) {
        alert("Horizontal Scrollbar! D:<");
    }
});

15
+1,但为了准确起见,这仅检查内容是否扩展到视口之外。如果 bodyoverflow 属性在某个地方设置为 hidden,它将无效。不过,在 body 上设置隐藏非常罕见。 - Pekka
5
如果文档高度完全匹配视窗高度,则此方法无效,因为这时会出现水平滚动条。它会强制出现垂直滚动条,但如果文档/主体/窗口高度相同,则不会提示“垂直滚动条”,即使存在垂直滚动条。 - Stop Slandering Monica Cellio
2
我想提一下,当$("body")无法使用时,我不得不使用$(document),这对我起作用了(我有一个宽高比上的绝对定位容器)。 - am_
1
我在Chrome浏览器上有一个报告页面,它最初显示滚动条,但在几毫秒内消失了,这看起来像是浏览器的行为,因为我没有编程。所以在我的情况下,这个函数总是返回true。 - D777Stack
@TiuTalk 对我来说,$("body").height() 和 $(window).height() 返回相同的值,所以我使用 $(document).height() > $(window).height(),这对我有效。 - SarangK

90

试一下这个:

var hasVScroll = document.body.scrollHeight > document.body.clientHeight;

这只会告诉你垂直滚动高度是否大于可视内容的高度。变量hasVScroll将包含true或false。

如果您需要进行更彻底的检查,请将以下代码添加到上面的代码中:

// Get the computed style of the body element
var cStyle = document.body.currentStyle||window.getComputedStyle(document.body, "");

// Check the overflow and overflowY properties for "auto" and "visible" values
hasVScroll = cStyle.overflow == "visible" 
             || cStyle.overflowY == "visible"
             || (hasVScroll && cStyle.overflow == "auto")
             || (hasVScroll && cStyle.overflowY == "auto");

1
+1 很好!并且带有必要的计算样式(这也是我决定不参与这个问题的关键点 ;) - Pekka
你在 hasVScroll 前面缺少 var 关键字,还是故意将其设置为全局变量?我看到它在条件语句中检查 hasVScroll 的值之前,似乎它正在维护从先前检查中保留的状态。 - Triynko
1
这会导致当overflowY为'visible'时,hasVScroll始终为true,而不管scrollHeight是否大于clientHeight。也许你的意思是cStyle.overflow === 'scroll' - B T
7
以上代码无法工作。浏览器为Chrome 56。网址为:https://news.greylock.com/the-hierarchy-of-engagement-expanded-648329d60804#.w3zl8fs6p - Sebastien Lorber
1
@BT 当元素为 document.body 时,cStyle.overflow == "visible" 可以显示滚动条。但应该是 (hasVScroll && cStyle.overflow == "visible" && element.nodeName == "BODY")。此外,还需要检查 cStyle.overflow === 'scroll',正如您所指出的那样。 - mseifert
显示剩余4条评论

48

我尝试了之前的回答,但似乎不起作用。$("body").height()并不一定表示整个HTML的高度。

我已经纠正了解决方案,如下:

// Check if body height is higher than window height :) 
if ($(document).height() > $(window).height()) { 
    alert("Vertical Scrollbar! D:"); 
} 

// Check if body width is higher than window width :) 
if ($(document).width() > $(window).width()) { 
    alert("Horizontal Scrollbar! D:<"); 
} 

18
让我们重新探讨这个问题 ;) 谷歌没有提供简单的解决方案是有原因的。特殊情况和浏览器怪异行为会影响计算,这并不像看起来那么简单。
不幸的是,到目前为止,这里概述的解决方案存在问题。我并不是要贬低它们 - 它们是很好的起点,并涉及更健壮的方法所需的所有关键属性。但我不建议从任何其他答案中复制和粘贴代码,因为
  • 它们没有以可靠的跨浏览器方式捕获定位内容的效果。基于 body 大小的答案完全忽略了这一点(除非 body 本身被定位)。而那些检查 $( document ).width().height() 的答案则会受到 jQuery 对文档大小检测的错误 的影响。
  • 如果浏览器支持,依赖于 window.innerWidth 会导致您的代码无法检测移动浏览器中的滚动条,在那里滚动条的宽度通常为 0。它们只是暂时显示为覆盖层,并不占据文档空间。在移动设备上缩放也变成了一个问题(长话短说)。
  • 当人们明确设置 htmlbody 元素的溢出值为非默认值时,检测可能会出错(然后会发生什么有点复杂-请参见此说明)。
  • 在大多数答案中,不检测 body 的内边距、边框或外边距,从而扭曲结果。
我花费的时间比想象中更长,寻找一个“只是工作”的解决方案(咳咳)。我所想出的算法现在是一个插件jQuery.isInView的一部分,该插件公开了一个.hasScrollbar方法。如果您愿意,请查看源码
在你完全控制页面且不必处理未知CSS的情况下,使用插件可能过度 - 毕竟,你知道哪些边界情况适用,哪些不适用。然而,如果您需要在未知环境中获得可靠的结果,那么我认为这里概述的解决方案将不够。最好使用经过充分测试的插件 - 我的或别人的插件。

谢谢。这有点复杂!如果您不想/不需要向后兼容,那么HTML5浏览器是否有更简单的解决方案?我的意思是,也许浏览器编码人员/W3C已经很好地告诉我们元素上是否有滚动条了?;-) - Leo
1
@Leo 我不知道有没有类似的功能。虽然有一个 window.scrollbars 对象,它有一个单一属性 visible,听起来很有希望,但事实并非如此。它不支持IE,包括IE11。而且它只告诉你有一个滚动条——但不是哪个滚动条。请参见这里的测试页面 - hashchange
感谢@hashchange。它只是告诉是否有滚动条,听起来非常愚蠢,所以我猜它只是某种测试。不过还是有点希望的。;-) - Leo
1
@BT 好的,很好。现在让我带你进入兔子洞的入口。这里有一个演示,内容不足以填满窗口。你的检测在FF中有效但在Chrome中失败。还有另一个演示,其中一个定位元素被放置在页面底部。你的检测在Chrome中有效但在FF中失败。 - hashchange
1
@BT 我猜当我们开始玩溢出设置时,可能会遇到一堆奇怪的故障模式,因为它们的行为有点奇怪,但我已经停在那里了。 - hashchange
显示剩余7条评论

17
let hasScrollbar = window.innerWidth > document.documentElement.clientWidth;

2
这个完成了任务,谢谢。 - Vignesh Chinnaiyan
1
是的,这个可以运行。 - Gopipuli

16

这个对我起作用了:

function hasVerticalScroll(node){
    if(node == undefined){
        if(window.innerHeight){
            return document.body.offsetHeight> window.innerHeight;
        }
        else {
            return  document.documentElement.scrollHeight > 
                document.documentElement.offsetHeight ||
                document.body.scrollHeight>document.body.offsetHeight;
        }
    }
    else {
        return node.scrollHeight> node.offsetHeight;
    }
}

关于页面主体,只需使用hasVerticalScroll()函数。


这是这个帖子中唯一在我的Chrome上有效的答案。 - Nertan Lucian
在这里,clientHeightoffsetHeight更可取。否则,当有滚动条时,您可能会有一个粗边框,并返回没有滚动条。 - theicfire

3
    <script>
    var scrollHeight = document.body.scrollHeight;
    var clientHeight = document.documentElement.clientHeight;
    var hasVerticalScrollbar = scrollHeight > clientHeight;

    alert(scrollHeight + " and " + clientHeight); //for checking / debugging.
    alert("hasVerticalScrollbar is " + hasVerticalScrollbar + "."); //for checking / debugging.
    </script>

这段代码可以判断你的页面是否有滚动条。我已经添加了一些调试信息,会以JavaScript警告框的形式显示出来。
将此代码放在结束body标签后的script标签中即可。

3

奇怪的是,这些解决方案都没有告诉你页面是否有垂直滚动条。

window.innerWidth - document.body.clientWidth将给出滚动条的宽度。这在IE9+(未在更低版本浏览器中测试)中应该有效。(或者严格回答问题,!!(window.innerWidth - document.body.clientWidth)

为什么呢?假设您有一个页面,其内容高度超过窗口高度,用户可以向上/向下滚动。如果您在Mac上使用Chrome而没有插入鼠标,则用户将看不到滚动条。插入鼠标,滚动条将出现。(请注意,此行为可以被覆盖,但我认为这是默认行为)。


Chrome-Mouse行为的解释帮助我弄清楚了我认为不一致的行为。谢谢! - theisof

2
我找到了一个简单的解决方案。

var hasScrollbar = function() {
  // The Modern solution
  if (typeof window.innerWidth === 'number')
    return window.innerWidth > document.documentElement.clientWidth

  // rootElem for quirksmode
  var rootElem = document.documentElement || document.body

  // Check overflow style property on body for fauxscrollbars
  var overflowStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowStyle = rootElem.currentStyle.overflow

  overflowStyle = overflowStyle || window.getComputedStyle(rootElem, '').overflow

    // Also need to check the Y axis overflow
  var overflowYStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowYStyle = rootElem.currentStyle.overflowY

  overflowYStyle = overflowYStyle || window.getComputedStyle(rootElem, '').overflowY

  var contentOverflows = rootElem.scrollHeight > rootElem.clientHeight
  var overflowShown    = /^(visible|auto)$/.test(overflowStyle) || /^(visible|auto)$/.test(overflowYStyle)
  var alwaysShowScroll = overflowStyle === 'scroll' || overflowYStyle === 'scroll'

  return (contentOverflows && overflowShown) || (alwaysShowScroll)
}


1
在IE 11中无法工作。window.innerWidth和document.documentElement.clientWidth始终相同。 - NLV
已解决。这个函数在IE 11中也可以工作。问题出在这里 - https://dev59.com/KWQn5IYBdhLWcg3wJ0i5 - NLV
我在Chrome 65中测试了它并且它可以工作。但是当我为水平滚动条进行适应时,结果很奇怪:如果同时显示水平和垂直滚动条,则window.innerWidth>document.documentElement.clientWidth为真,但是window.innerHeight > document.documentElement.clientHeight不为真。在这种情况下,它看起来就像是反过来的。我不是一个JS开发人员,我只需要它用于Selenium测试。我感激任何提示。 - kriegaex

2

只需比较文档根元素(即html元素)的宽度与窗口的内部部分:

if ((window.innerWidth - document.documentElement.clientWidth) >0) console.log('V-scrollbar active')

如果您还需要知道滚动条的宽度:
vScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

这是一个聪明的解决方案,可以处理HTML元素具有overflow-y:scroll但页面上实际没有溢出的边缘情况。其他检查溢出高度的解决方案无法解决此问题。 - kimbaudi

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