【问题标题】:How to disable body scrolling when modal is open IOS only仅当模式打开 IOS 时如何禁用正文滚动
【发布时间】:2019-07-14 04:13:43
【问题描述】:

仅限IOS / iPhone X / iPhone 7等

即使是 jquery 模态库也不起作用! https://jquerymodal.com/ - 在 iPhone 上打开模态框,您将能够滚动正文。

我发现很难找到一种解决方案,可以在每次打开模式时停止正文滚动而不使页面跳转到顶部(这与页面滚动一样糟糕)

这似乎是一个很多人都遇到过的大问题。正如你在这里看到的:

我在网上搜寻了没有运气,有人有解决办法吗?!

【问题讨论】:

    标签: html css twitter-bootstrap-3 bootstrap-modal


    【解决方案1】:

    经过多次尝试,我想出了:

    /* Default (phone) */
    body.modal-open {
        left: 0;
        position: fixed;
        right: 0;
        /* Prevent scrolling of body */
        overflow-y: hidden !important;
    }
    
    /* Small and above e.g. not a phone */
    @media (min-width: 576px) {
        body.modal-open {
            /* Keep scrollbar */
            overflow-y: scroll !important;
        }
    }
    

    在默认模式(电话)下,我只是删除了垂直滚动条。由于它在手机上,它位于顶部,并且没有宽度。没有overflow-y,手机无法滚动。

    但在桌面上,我喜欢永久的水平滚动,所以我在模态时强制打开它以防止屏幕移动 17px 宽度。

    如果在桌面(全宽滚动条)上,如果用户将浏览器缩小到小于 576 像素,你会得到一个转变,但我可以忍受。

    另外——我允许在模式中滚动。这样,模态不会在移动设备上从屏幕底部跑出。

    【讨论】:

      【解决方案2】:

      export default class BackgroundScroll {
        private scrollPosition = 0;
        disable = (isDisable) => {
          if (isDisable) {
            this.scrollPosition = window.pageYOffset;
            document.body.classList.add('block-body-scroll');
            document.body.style.top = `-${this.scrollPosition}px`;
            if (this.checkIos()) {
              document.body.classList.add('ios');
            }
          } else {
            document.body.classList.remove('block-body-scroll');
            window.scrollTo(0, this.scrollPosition);
          }
        };
      
        private checkIos(): boolean {
          return (
            ['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(
              navigator.platform
            ) ||
            (navigator.userAgent.includes('Mac') && 'ontouchend' in document)
          );
        }
      }
      body.block-body-scroll {
        overflow: hidden;
        width: 100%;
        &.ios {
          position: fixed;
        }
      }

      我们只为 ios 处理 position: fixed。因为position: fixed会影响其他浏览器如火狐。这是我在 typescript 上处理的代码,但纯 JS 或其他任何东西与我的基本相同。

      【讨论】:

        【解决方案3】:

        我创建了以下解决方案,适用于 iOS 12!

        虽然下面的嵌入式演示使用的是 Bootstrap 4,但同样的解决方案也适用于 Bootstrap 3,因为所有模式类或事件名称都不同。

        第 1 步:在模态打开时使用固定定位将body 冻结到位

        当一个 Bootstrap 模态打开时,一个名为 .modal-open 的类被添加到 body 中。将以下附加样式添加到此类:

        body {
            &.modal-open {
                bottom: 0;
                left: 0;
                position: fixed;
                right: 0;
                top: 0;
            }
        }
        

        现在,每当打开模式时,body 将固定在适当的位置,并调整为与视口本身相同的尺寸。这完全阻止了滚动,因为没有任何地方可以滚动!

        但是:这也意味着打开模态框会导致页面跳转到顶部,因为body 不再超出视口的底部边缘(假设页面内容更高)。

        第 2 步:在模态打开时模拟之前的滚动距离

        Bootstrap 公开在打开或关闭模式时触发的事件。我们可以使用这些来解决“跳到顶部”的问题,方法是在打开模式时拉动body up 的顶部,这样看起来滚动位置没有改变:

        $(function() {
            var $window = $(window),
                $body = $("body"),
                $modal = $(".modal"),
                scrollDistance = 0;
        
            $modal.on("show.bs.modal", function() {
                // Get the scroll distance at the time the modal was opened
                scrollDistance = $window.scrollTop();
        
                // Pull the top of the body up by that amount
                $body.css("top", scrollDistance * -1);
            });
        });
        

        但是,当模态框关闭时页面仍然会跳转到顶部,因为windowscrollTop值仍然是0

        第 3 步:关闭模式时重置所有内容

        现在我们只需要挂钩在模式关闭时触发的事件,并将所有内容恢复原状:

        • 移除body上的固定定位和负上限值
        • 将窗口的滚动位置设置回原来的位置
        $modal.on("hidden.bs.modal", function() {
            // Remove the negative top value on the body
            $body.css("top", "");
        
            // Set the window's scroll position back to what it was before the modal was opened
            $window.scrollTop(scrollDistance);  
        });
        

        无需手动移除body 上的固定定位,因为这是通过.modal-open 类设置的,Bootstrap 会在模态关闭时移除该类。


        演示

        将它们放在一起,现在您可以在模式打开时阻止 iOS 上的背景滚动,而不会丢失滚动位置!

        在 iOS 设备上打开以下链接:https://daguy.github.io/ios-modal-fix/

        【讨论】:

        • 我已经在我的 iPhone 上用这个 codepen 尝试过这个代码:codepen.io/bkdigital/pen/YBbpvN - 它似乎不起作用,请在你的 iPhone 设备上尝试一下?您只能看到页面顶部,无论模态是否打开,正文都会被切断。
        • 您有使用过此解决方案的网站吗? @daGuy
        • @BennKingy – 看起来 Codepen 本身以某种方式干扰了它。它在我在独立页面上运行 iOS 12 的 iPhone XR 上完美运行:daguy.github.io/ios-modal-fix
        • 在页面的顶部和底部都有打开模态的按钮,这样你就可以看到它在不同的滚动位置是如何工作的。
        • 我已经在那里测试了你的链接并且它的工作完美!血腥的代码笔:P 我今天将实现这个 TYVM!
        【解决方案4】:

        嗯,我看到关于 SO 的主题很少。 试试这个吧?

        @supports (-webkit-overflow-scrolling: touch) {
          /* CSS specific to iOS devices */ 
        }
        
        @supports not (-webkit-overflow-scrolling: touch) {
          /* CSS for other than iOS devices */ 
        }
        

        CSS media query target only iOS devices

        【讨论】:

        • 我不需要 IOS 特定的样式 hack,我需要在 IOS 上打开模式时停止正文滚动。
        猜你喜欢
        • 2019-04-16
        • 2015-07-05
        • 1970-01-01
        • 1970-01-01
        • 2019-10-14
        • 2017-02-10
        • 2014-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多