准确确定元素是否可滚动

McC*_*key 12 html jquery knockout.js

我正在开发一个自定义的knockout绑定,用于确定是否正在滚动特定元素,并使用元素相对于视口的顶部更新绑定的observable.现在,绑定似乎有效,但我担心是否存在某些情况不会发生.

HTML:

Scroll position: <span data-bind="text: scrollPosition"></span>

<div class="longdiv">    
    <p data-bind="scroll: scrollPosition">This is some text.</p>
    <div class="shim"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

CSS:

.longdiv {
    width: 200px;
    height: 200px;
    overflow: scroll;
    border: 1px solid black;
}
Run Code Online (Sandbox Code Playgroud)

JS:

ko.bindingHandlers.scroll = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var firstScrollableContainer = null;

        var binding = allBindings.get('scroll');

        $(element).parents().each(function (i, parent) {
            if ($(parent).css('overflow')=='scroll') {
                firstScrollableContainer = parent;
                return false;
            }
        });

        firstScrollableContainer = firstScrollableContainer || window;                

        binding(element.getBoundingClientRect().top);

        $(firstScrollableContainer).scroll(function() {            
            binding(element.getBoundingClientRect().top);
        });
    }
};

var ViewModel = function() {
    var self = this;

    self.scrollPosition = ko.observable(0);
};

ko.applyBindings(new ViewModel());
Run Code Online (Sandbox Code Playgroud)

的jsfiddle

绑定接受元素并使用jQuery走向父链,以查看父元素是否有溢出:scroll set.如果它找到一个带溢出的div:scroll,它会将一个事件处理程序绑定到该元素的scroll事件.如果找不到具有溢出的父级:滚动,则它会绑定到窗口的滚动事件.

所以我正在寻找,给出一个像这样结构的文档:

body > div > div > div > p
Run Code Online (Sandbox Code Playgroud)

是最接近p的包含元素,可以滚动,以便我可以附加一个事件处理程序.

我的问题是:正在查看溢出:滚动一个足够的测试,看看是否可以滚动父元素?如果没有,我应该看什么?

编辑:基于您的有用的评论和答案,这是我提出的解决方案:

function scrollable(element) {
    var vertically_scrollable, horizontally_scrollable;

    var e = $(element);

     if (   e.css('overflow') == 'scroll' 
         || e.css('overflow') == 'auto'
         || e.css('overflowY') == 'scroll'
         || e.css('overflowY') == 'auto'
         || e.css('height') != 'none'
         || e.css('max-height') != 'none'                          
         ) {
         return true;
    } else {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

Raf*_*lKr 12

这可能是最好的解决方案:

$.fn.isHScrollable = function () {
    return this[0].scrollWidth > this[0].clientWidth;
};

$.fn.isVScrollable = function () {
    return this[0].scrollHeight > this[0].clientHeight;
};

$.fn.isScrollable = function () {
    return this[0].scrollWidth > this[0].clientWidth || this[0].scrollHeight > this[0].clientHeight;
};
Run Code Online (Sandbox Code Playgroud)

然后你可以检查元素是否可滚动如下:

$(parent).isScrollable();
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案可以为具有“overflow:hidden”或“overflow:visible”的元素返回“true”→这些情况可以具有滚动高度&gt;客户端高度而不可滚动 (4认同)

Mic*_*est 10

你想知道一个元素是否可以滚动或当前可以滚动?

元素可以滚动吗?

如果元素具有固定height(或max-height)并且overflow-yscroll或,则可以滚动auto.但由于要判断元素的高度是否固定并不容易,所以只需检查overflow-y:

e.css('overflow-y') == 'scroll' || e.css('overflow-y') == 'auto'
Run Code Online (Sandbox Code Playgroud)

元素现在可以滚动吗?

如果元素scrollHeight大于它clientHeight并且它有滚动条,则可以立即滚动元素,这可以通过比较clientWidthoffsetWidth(考虑边距和边界)或检查是否overflow-yscroll或来确定auto.


ali*_*dil 6

将两个答案合并在一起,并添加一些我自己的东西,这就是我用来检查垂直滚动的方法。它可以很容易地转换为其他情况。(H 和 VH)

function isScrollable(e){
    if( e.scrollTopMax !== undefined )
        return e.scrollTopMax > 0; //All Hail Firefox and it's superior technology!

    if( e == document.scrollingElement ) //If what you're checking is BODY (or HTML depending on your css styles)
        return e.scrollHeight > e.clientHeight; //This is a special case.

    return e.scrollHeight > e.clientHeight && ["scroll", "auto"].indexOf(getComputedStyle(e).overflowY) >= 0



}
Run Code Online (Sandbox Code Playgroud)

我在 Firefox 和 Chromium 上对此进行了测试。两者都是Linux。不过,您可能仍然想亲自检查一下。