iOS 10 Safari:防止在固定叠加层后面滚动并保持滚动位置

Gav*_*vin 33 javascript css safari ios ios10

当显示固定位置叠加时,我无法阻止主体内容滚动.类似的问题已被多次询问,但以前工作的所有技术似乎都不适用于iOS 10中的Safari.这似乎是最近的一个问题.

一些说明:

  • 如果我都设为我可以禁用滚动htmlbodyoverflow: hidden,然而,使主体内容滚动到顶部.
  • 如果覆盖中的内容足够长以便可以滚动,则对主页内容正确禁用滚动.如果叠加层中的内容不足以导致滚动,则可以滚动主页面内容.
  • 我在http://blog.christoffer.me/six-things-i-learnt-about-ios-safaris-rubber-band-scrolling/中添加了一个javascript函数,该函数touchmove在叠加显示时禁用.这在以前工作,但不再有效.

这是完整的HTML源代码:

<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <style type="text/css">
        html, body {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: arial;
        }
        #overlay {
            display: none;
            position: fixed;
            z-index: 9999;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            overflow: scroll;
            color: #fff;
            background: rgba(0, 0, 0, 0.5);
        }
        #overlay span {
            position: absolute;
            display: block;
            right: 10px;
            top: 10px;
            font-weight: bold;
            font-size: 44px;
            cursor: pointer;
        }
        #overlay p {
            display: block;
            padding: 100px;
            font-size: 36px;
        }
        #page {
            width: 100%;
            height: 100%;
        }
        a {
            font-weight: bold;
            color: blue;
        }
    </style>
    <script>
        $(function() {
            $('a').click(function(e) {
                e.preventDefault();
                $('body').css('overflow', 'hidden');
                $('#page').addClass('disable-scrolling'); // for touchmove technique below

                $('#overlay').fadeIn();
            });
            $('#overlay span').click(function() {
                $('body').css('overflow', 'auto');
                $('#page').removeClass('disable-scrolling'); // for touchmove technique below

                $('#overlay').fadeOut();
            });
        });

        /* Technique from http://blog.christoffer.me/six-things-i-learnt-about-ios-safaris-rubber-band-scrolling/ */
        document.ontouchmove = function ( event ) {
            var isTouchMoveAllowed = true, target = event.target;
            while ( target !== null ) {
                if ( target.classList && target.classList.contains( 'disable-scrolling' ) ) {
                    isTouchMoveAllowed = false;
                    break;
                }
                target = target.parentNode;
            }
            if ( !isTouchMoveAllowed ) {
                event.preventDefault();
            }
        };
    </script>
</head>

<body>
    <div id="overlay">
        <span>&times;</span>
        <p>fixed popover</p>
    </div>

    <div id="page">
        <strong>this is the top</strong><br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        lots of scrollable content<br>
        asdfasdf<br>
        <br>
        <div><a href="#">Show Popover</a></div>
        <br>
        <br>

    </div>

</body>

</html>
Run Code Online (Sandbox Code Playgroud)

Boh*_*ukh 55


请添加-webkit-overflow-scrolling: touch;#overlay元素.

并在body标签的末尾添加此javascript代码:

(function () {
    var _overlay = document.getElementById('overlay');
    var _clientY = null; // remember Y position on touch start

    _overlay.addEventListener('touchstart', function (event) {
        if (event.targetTouches.length === 1) {
            // detect single touch
            _clientY = event.targetTouches[0].clientY;
        }
    }, false);

    _overlay.addEventListener('touchmove', function (event) {
        if (event.targetTouches.length === 1) {
            // detect single touch
            disableRubberBand(event);
        }
    }, false);

    function disableRubberBand(event) {
        var clientY = event.targetTouches[0].clientY - _clientY;

        if (_overlay.scrollTop === 0 && clientY > 0) {
            // element is at the top of its scroll
            event.preventDefault();
        }

        if (isOverlayTotallyScrolled() && clientY < 0) {
            //element is at the top of its scroll
            event.preventDefault();
        }
    }

    function isOverlayTotallyScrolled() {
        // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
        return _overlay.scrollHeight - _overlay.scrollTop <= _overlay.clientHeight;
    }
}())
Run Code Online (Sandbox Code Playgroud)

我希望它对你有所帮助.

  • 当覆盖毯位于顶部时,我必须复制所有 js 才能在后台禁用滚动?我希望有一个更优雅的解决方案 (3认同)

Wil*_* Po 8

将Bohdan Didukh的方法与我以前的方法相结合,以创建易于使用的npm包来禁用/启用身体滚动。

https://github.com/willmcpo/body-scroll-lock

有关该解决方案如何工作的更多详细信息,请阅读https://medium.com/jsdownunder/locking-body-scroll-for-all-devices-22def9615177


Fir*_*Dib 6

很长一段时间以来,我一直试图为此找到一个干净的解决方案,似乎对我最有效的方法是pointer-events: none;在正文上进行设置,然后pointer-events: auto;在我想要允许滚动的项目上明确设置。

  • 在 iOS 12 上试过,没有效果:/ (3认同)