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

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个回答

4
我会进一步扩展这个内容,特别是为那些像我一样使用现代js框架而不是JQuery的可怜人提供帮助,并且已经被此线程中的人完全抛弃:
这是在Angular 6中编写的,但如果你编写React 16、Vue 2、Polymer、Ionic、React-Native,你就知道如何适应它了。而且它是整个组件,所以应该很容易。
import {ElementRef, AfterViewInit} from '@angular/core';

@Component({
  selector: 'app',
  templateUrl: './app.html',
  styleUrls: ['./app.scss']
})
export class App implements AfterViewInit {
scrollAmount;

constructor(
  private fb: FormBuilder,
  private element: ElementRef 
) {}

ngAfterViewInit(){
  this.scrollAmount = this.element.nativeElement.querySelector('.elem-list');
  this.scrollAmount.addEventListener('wheel', e => { //you can put () instead of e
  // but e is usefull if you require the deltaY amount.
    if(this.scrollAmount.scrollHeight > this.scrollAmount.offsetHeight){
       // there is a scroll bar, do something!
    }else{
       // there is NO scroll bar, do something!
    }
  });
}
}

在 HTML 中,会有一个带有类名“elem-list”的 div 元素,该元素在 CSS 或 SCSS 中被设置了高度和 overflow 值(不是 hidden,而是 auto 或 scroll)。

我会在滚动事件触发时启动此评估,因为我的最终目标是实现“自动焦点滚动”,即根据组件是否具有垂直滚动条来决定它们是水平滚动整个组件集还是仅垂直滚动一个组件的内部。

但你也可以将这个评估放在其他地方,由其他事件触发。

重要的是记住,你永远不会被迫使用 JQuery,总有一种方法可以访问它具有的相同功能而不使用它。


1
你为什么要监听滚轮事件来检查是否有滚动条,这让我很好奇。 - mix3d
3
由于您正在使用箭头函数,因此this将保留其父范围; th = this;是不必要的。 - mix3d
1
@mix3d 我个人使用这段代码来自动切换水平和垂直滚动,根据给定的动态元素的滚动方向。 - tatsu
1
关于这个问题,它基本上是语法糖(加上不错的简写),等同于 function(){}.bind(this) - mix3d

3
上述提供的解决方案在大多数情况下都有效,但有时仅检查scrollHeight和overflow是不够的,可能会对body和html元素失效,如此处所示: https://codepen.io/anon/pen/EvzXZw

1. 解决方案 - 检查元素是否可滚动:

function isScrollableY (element) {
  return !!(element.scrollTop || (++element.scrollTop && element.scrollTop--));
}

注意: 带有 overflow: hidden 属性的元素也被视为可滚动的(更多信息),因此如果需要,您也可以针对这一点添加条件:

function isScrollableY (element) {
    let style = window.getComputedStyle(element);
    return !!(element.scrollTop || (++element.scrollTop && element.scrollTop--)) 
           && style["overflow"] !== "hidden" && style["overflow-y"] !== "hidden";
}

据我所知,只有在元素具有scroll-behavior: smooth时,该方法才会失败。 解释:诀窍在于,尝试向下滚动并撤销滚动操作不会被浏览器呈现。最上面的函数也可以写成以下形式:

function isScrollableY (element) {
  // if scrollTop is not 0 / larger than 0, then the element is scrolled and therefore must be scrollable
  // -> true  
  if (element.scrollTop === 0) {
    // if the element is zero it may be scrollable  
    // -> try scrolling about 1 pixel
    element.scrollTop++;
    // if the element is zero then scrolling did not succeed and therefore it is not scrollable 
    // -> false  
    if (element.scrollTop === 0) return false;
    // else the element is scrollable; reset the scrollTop property
    // -> true
    element.scrollTop--;
  }
  return true;
}

2. 解决方案 - 执行所有必要的检查:

function isScrollableY (element) {
  const style = window.getComputedStyle(element);
  
  if (element.scrollHeight > element.clientHeight &&
      style["overflow"] !== "hidden" && style["overflow-y"] !== "hidden" &&
      style["overflow"] !== "clip" && style["overflow-y"] !== "clip"
  ) {
    if (element === document.scrollingElement) return true;
    else if (style["overflow"] !== "visible" && style["overflow-y"] !== "visible") {
      // special check for body element (https://drafts.csswg.org/cssom-view/#potentially-scrollable)
      if (element === document.body) {
        const parentStyle = window.getComputedStyle(element.parentElement);
        if (parentStyle["overflow"] !== "visible" && parentStyle["overflow-y"] !== "visible" &&
            parentStyle["overflow"] !== "clip" && parentStyle["overflow-y"] !== "clip"
        ) {
          return true;
        }
      }
      else return true;
    }
  }
  
  return false;
}

解决方案1对我有效。 - vaid

1
大多数回答都让我接近目标,但还没有完全达到。

我们基本上想要评估滚动条是否在正常情况下可见,根据该定义,意味着body元素的大小大于视口。这不是一个提出的解决方案,这就是为什么我提交它的原因。

希望能对某人有所帮助!

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

基本上,我们有一个名为hasScrollbar的函数,但是返回的是请求元素是否大于视口。对于视口大小,我们只使用了$(window).height()。将其与元素大小进行快速比较,可以得出正确的结果和期望的行为。

1
这是Evan答案的改进版本,似乎正确考虑了溢出逻辑。
            function element_scrollbars(node) {
                var element = $(node);
                var overflow_x = element.css("overflow-x");
                var overflow_y = element.css("overflow-y");
                var overflow = element.css("overflow");
                if (overflow_x == "undefined") overflow_x == "";
                if (overflow_y == "undefined") overflow_y == "";
                if (overflow == "undefined") overflow == "";
                if (overflow_x == "") overflow_x = overflow;
                if (overflow_y == "") overflow_y = overflow;
                var scrollbar_vertical = (
                    (overflow_y == "scroll")
                    || (
                        (
                            (overflow_y == "hidden")
                            || (overflow_y == "visible")
                        )
                        && (
                            (node.scrollHeight > node.clientHeight)
                        )
                    )
                );
                var scrollbar_horizontal = (
                    (overflow_x == "scroll")
                    || (
                        (
                            (overflow_x == "hidden")
                            || (overflow_x == "visible")
                        )
                        && (
                            (node.scrollWidth > node.clientWidth)
                        )
                    )
                );
                return {
                    vertical: scrollbar_vertical,
                    horizontal: scrollbar_horizontal
                };
            }

0

找到当前元素的父级,该父级具有垂直滚动或者是body。

$.fn.scrollableParent = function() {
    var $parents = this.parents();

    var $scrollable = $parents.filter(function(idx) {
        return this.scrollHeight > this.offsetHeight && this.offsetWidth !== this.clientWidth;
    }).first();

    if ($scrollable.length === 0) {
        $scrollable = $('html, body');
    }
    return $scrollable;
};

可以通过以下方式将页面自动滚动到当前元素:

var $scrollable = $elem.scrollableParent();
$scrollable.scrollTop($elem.position().top);

0

适用于Chrome、Edge、Firefox和Opera,至少在较新的版本中可用。

使用JQuery...

设置此函数以修复页脚:

function fixFooterCaller()
{
    const body = $('body');
    const footer = $('body footer');

    return function ()
    {
        // If the scroll bar is visible
        if ($(document).height() > $(window).height())
        {
            // Reset
            footer.css('position', 'inherit');
            // Erase the padding added in the above code
            body.css('padding-bottom', '0');
        }
        // If the scrollbar is NOT visible
        else
        {
            // Make it fixed at the bottom
            footer.css('position', 'fixed');
            // And put a padding to the body as the size of the footer
            // This makes the footer do not cover the content and when
            // it does, this event fix it
            body.css('padding-bottom', footer.outerHeight());
        }
    }
}

它返回一个函数。这样做只是为了一次设置正文和页脚。
然后,在文档准备好时进行设置。
$(document).ready(function ()
{
    const fixFooter = fixFooterCaller();

    // Put in a timeout call instead of just call the fixFooter function
    // to prevent the page elements needed don't be ready at this time
    setTimeout(fixFooter, 0);
    // The function must be called every time the window is resized
    $(window).resize(fixFooter);
});

将以下内容添加到您的页脚 CSS 中:
footer {
    bottom: 0;
}

0
这是我的改进:添加parseInt。因为某些奇怪的原因,如果没有它就无法正常工作。
// usage: jQuery('#my_div1').hasVerticalScrollBar();
// Credit: https://dev59.com/l2445IYBdhLWcg3wiayV
(function($) {
    $.fn.hasVerticalScrollBar = function() {
        return this.get(0) ? parseInt( this.get(0).scrollHeight ) > parseInt( this.innerHeight() ) : false;
    };
})(jQuery);

0

我遇到了一个问题,需要检查滚动条是否在整个屏幕(body)上可见。Chrome有隐藏滚动条的能力,尽管存在溢出情况,因此body是可滚动的。

因此,上面的解决方案对我不起作用。现在我通过以下方式检查是否有滚动条:

const isScrollbarPresent = () => {
    const beforeScrollbarHidden = document.body.clientWidth;
    const overflowState = document.body?.style.overflow;
    document.body.style.overflow = 'hidden';
    const afterScrollbarHidden = document.body.clientWidth;
    document.body.style.overflow = overflowState;
    return beforeScrollbarHidden !== afterScrollbarHidden;
};

我获取页面主体的宽度,包括或不包括滚动条,并保存当前主体的溢出状态。然后我隐藏滚动条。如果存在滚动条,则主体的宽度现在更大。如果没有滚动条,则宽度保持不变。之后我恢复溢出状态。


0

另一个简单的答案如下:

export const isScrollbarPresent = (element?: HTMLElement) => {
const testedElement = element ?? document.body;
return testedElement.scrollHeight > testedElement.clientHeight; }

我检查元素的scrollHeight是否大于clientHeight。scrollHeight返回一个元素的绝对高度,包括所有不可见的元素。clientHeight返回屏幕上可见的高度。

0

需要考虑两个区域的大小,即窗口和HTML。例如,如果HTML宽度大于窗口宽度,则用户界面上可能会出现滚动条。因此,关键是读取窗口比例和HTML比例并进行基本数学计算。

至于在页面上方显示重叠箭头,可以使用简单的类列表切换来完成,例如.hidden{display:none}

以下是一个跨浏览器获取这些比例的方法。(来源W3 Schools

|| document.body.clientWidth;

var h = window.innerHeight || document.documentElement.clientHeight ||
document.body.clientHeight; ```

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