How to prevent document scrolling but allow scrolling inside div elements on websites for iOS and Android?

后端 未结 11 1457
南笙
南笙 2020-12-04 10:43

I created a website with jQueryMobile for iOS and Android.

I don\'t want the document itself to scroll. Instead, just an area (a

element) sh
11条回答
  •  有刺的猬
    2020-12-04 11:27

    I was looking for a solution that did not require calling out specific areas that should scroll. Piecing together a few resources, here is what worked for me:

        // Detects if element has scroll bar
        $.fn.hasScrollBar = function() {
            return this.get(0).scrollHeight > this.outerHeight();
        }
    
        $(document).on("touchstart", function(e) {
            var $scroller;
            var $target = $(e.target);
    
            // Get which element could have scroll bars
            if($target.hasScrollBar()) {
                $scroller = $target;
            } else {
                $scroller = $target
                    .parents()
                    .filter(function() {
                        return $(this).hasScrollBar();
                    })
                    .first()
                ;
            }
    
            // Prevent if nothing is scrollable
            if(!$scroller.length) {
                e.preventDefault();
            } else {
                var top = $scroller[0].scrollTop;
                var totalScroll = $scroller[0].scrollHeight;
                var currentScroll = top + $scroller[0].offsetHeight;
    
                // If at container edge, add a pixel to prevent outer scrolling
                if(top === 0) {
                    $scroller[0].scrollTop = 1;
                } else if(currentScroll === totalScroll) {
                    $scroller[0].scrollTop = top - 1;
                }
            }
        });
    

    This code requires jQuery.

    Sources:

    • this post
    • https://github.com/luster-io/prevent-overscroll
    • How can I check if a scrollbar is visible?
    • Jquery check if any parent div have scroll bar

    Update

    I needed a vanilla JavaScript version of this, so the following is a modified version. I implemented a margin-checker and something that explicitly allows input/textareas to be clickable (I was running into issues with this on the project I used it on...it may not be necessary for your project). Keep in mind this is ES6 code.

    const preventScrolling = e => {
        const shouldAllowEvent = element => {
            // Must be an element that is not the document or body
            if(!element || element === document || element === document.body) {
                return false;
            }
    
            // Allow any input or textfield events
            if(['INPUT', 'TEXTAREA'].indexOf(element.tagName) !== -1) {
                return true;
            }
    
            // Get margin and outerHeight for final check
            const styles = window.getComputedStyle(element);
            const margin = parseFloat(styles['marginTop']) +
                parseFloat(styles['marginBottom']);
            const outerHeight = Math.ceil(element.offsetHeight + margin);
    
            return (element.scrollHeight > outerHeight) && (margin >= 0);
        };
    
        let target = e.target;
    
        // Get first element to allow event or stop
        while(target !== null) {
            if(shouldAllowEvent(target)) {
                break;
            }
    
            target = target.parentNode;
        }
    
        // Prevent if no elements
        if(!target) {
            e.preventDefault();
        } else {
            const top = target.scrollTop;
            const totalScroll = target.scrollHeight;
            const currentScroll = top + target.offsetHeight;
    
            // If at container edge, add a pixel to prevent outer scrolling
            if(top === 0) {
                target.scrollTop = 1;
            } else if(currentScroll === totalScroll) {
                target.scrollTop = top - 1;
            }
        }
    };
    
    document.addEventListener('touchstart', preventScrolling);
    document.addEventListener('mousedown', preventScrolling);
    

提交回复
热议问题