【问题标题】:How to prevent background scrolling when Bootstrap 3 modal open on mobile browsers?在移动浏览器上打开 Bootstrap 3 模式时如何防止背景滚动?
【发布时间】:2013-09-27 21:25:47
【问题描述】:

在移动平台上打开 Bootstrap 3 modal 时如何防止背景滚动?在桌面浏览器上,背景被阻止滚动并正常工作。

在移动浏览器(Safari ios、Chrome ios 等)上,当打开模态并使用手指滚动它时,背景也会像模态一样滚动。我该如何预防?

【问题讨论】:

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


    【解决方案1】:

    请看这里:https://github.com/twbs/bootstrap/issues/7501

    那就试试吧:

    $('body').css('overflow','hidden');
    $('body').css('position','fixed');
    

    V3.0.0。应该已经解决了这个问题。你用的是最新版本吗?如果是这样,请在https://github.com/twbs/bootstrap/ 上发布问题

    【讨论】:

    • 谢谢,就是这样。我有一些来自 BS 2 的遗留代码把我搞砸了。
    • 我实际上在这里发布了这个问题 - github.com/twbs/bootstrap/issues/15852 - body.modal-open { position: fixed; } 有滚动到顶部的副作用...... (仍然不确定什么是最好的方法)
    • Michael Stefanow 您是否偶然发现了滚动到顶部的问题?我对这个修复有同样的问题。
    • 保持滚动位置的一件事我在加载覆盖时执行了以下操作保存滚动位置 [var scrollTop = document.getElementById("body").scrollTop] 当您关闭覆盖时恢复您的位置与 [document.getElementById("body").scrollTop = scrollTop;]
    • V3 没有解决这个问题
    【解决方案2】:

    试试这个,

     body.modal-open {
        overflow: hidden;
        position:fixed;
        width: 100%;
    }
    

    【讨论】:

    • 有滚动到顶部的副作用
    【解决方案3】:

    我尝试了接受的答案,该答案阻止了正文滚动,但出现了滚动到顶部的问题。这应该可以解决这两个问题。

    附带说明,它似乎溢出:隐藏在 iOS Safari 的主体上不起作用,只有 iOS Chrome 可以正常工作。

    var scrollPos = 0;
    
    $('.modal')
        .on('show.bs.modal', function (){
            scrollPos = $('body').scrollTop();
            $('body').css({
                overflow: 'hidden',
                position: 'fixed',
                top : -scrollPos
            });
        })
        .on('hide.bs.modal', function (){
            $('body').css({
                overflow: '',
                position: '',
                top: ''
            }).scrollTop(scrollPos);
        });
    

    【讨论】:

    【解决方案4】:
    $('.modal') 
    .on('shown', function(){ 
      console.log('show'); 
      $('body').css({overflow: 'hidden'}); 
    }) 
    .on('hidden', function(){ 
      $('body').css({overflow: ''}); 
    }); 
    

    用这个

    【讨论】:

      【解决方案5】:

      不需要脚本。

      BS 3 在 body 上设置了一个 .modal-open 类,您可以使用它来设置位置和溢出值(使用 LESS 制作)。

      body {
          font-family:'Open Sans';
          margin:0;
      
          &.modal-open {
              position:fixed;
              overflow:hidden;
      
              .modal { 
                  overflow: scroll;
      
                  @media only screen and (min-resolution:150dpi) and (max-width: @screen-sm),
                  only screen and (-webkit-min-device-pixel-ratio:1.5) {
                      overflow: scroll; 
                      -webkit-overflow-scrolling: touch; 
                  }
              }
          }   
      }
      

      【讨论】:

      • 能否提供一个演示
      • 有效吗?如果可能,请提供一些演示。谢谢。
      【解决方案6】:

      选择的解决方案有效,但它们也会将背景捕捉到顶部滚动位置。我扩展了上面的代码来修复那个“跳转”。

      //Set 2 global variables
      var scrollTopPosition = 0;
      var lastKnownScrollTopPosition = 0;
      
      //when the document loads
      $(document).ready(function(){
      
        //this only runs on the right platform -- this step is not necessary, it should work on all platforms
        if( navigator.userAgent.match(/iPhone|iPad|iPod/i) ) {
      
          //There is some css below that applies here
          $('body').addClass('platform-ios');
      
          //As you scroll, record the scrolltop position in global variable
          $(window).scroll(function () {
            scrollTopPosition = $(document).scrollTop();
          });
      
          //when the modal displays, set the top of the (now fixed position) body to force it to the stay in the same place
          $('.modal').on('show.bs.modal', function () {
      
            //scroll position is position, but top is negative
            $('body').css('top', (scrollTopPosition * -1));
      
            //save this number for later
            lastKnownScrollTopPosition = scrollTopPosition;
          });
      
          //on modal hide
          $('.modal').on('hidden.bs.modal', function () {
      
            //force scroll the body back down to the right spot (you cannot just use scrollTopPosition, because it gets set to zero when the position of the body is changed by bootstrap
            $('body').scrollTop(lastKnownScrollTopPosition);
          });
        }
      });
      

      css 非常简单:

      // You probably already have this, but just in case you don't
      body.modal-open {
        overflow: hidden;
        width: 100%;
        height: 100%;
      }
      //only on this platform does it need to be fixed as well
      body.platform-ios.modal-open {
        position: fixed;
      }
      

      【讨论】:

      • 谢谢。对我来说效果很好,在桌面和 ios 上进行了测试。我的最后一个问题是在我执行 ajax 操作后试图阻止在 iOS 上滚动到顶部。不会滚动到桌面顶部。
      • 没关系,将$('body').scrollTop(lastKnownScrollTopPosition); 也添加到我的 x.js.erb 文件(提交时执行 js 代码的文件)效果很好。谢谢!
      【解决方案7】:

      如果你使用 jQuery,你可以使用 scrollTop 来做到这一点

      1. 保存body的垂直滚动位置;
      2. 在 body 上禁用滚动;
      3. 显示模态;
      4. 关闭模态;
      5. 重新启用正文滚动;
      6. 设置保存的滚动位置。

      #modal {
          bottom: 0;
          position: fixed;
          overflow-y: scroll;
          overflow-x: hidden;
          top: 0;
          width: 100%;
      }

      $('.open-modal').click(function (e) {
          e.preventDefault();
          $('#modal').toggle();
          scrollTo = $('body').scrollTop();
          $('body').css("position", "fixed");
      });
      
      $('.close-modal').click(function (e) {
          e.preventDefault();
          $('#modal').toggle();
          $('body').css("position", "static");
          $('body').animate({scrollTop: scrollTo}, 0);
      });

      【讨论】:

        【解决方案8】:

        以上答案没有帮助,所以我所做的是:

        .modal {
          -webkit-overflow-scrolling: touch; 
        }
        

        我的特殊问题是加载后增加了模态大小。

        这是一个已知的 iOS 问题,see here。由于它不会破坏其他任何东西,因此上述解决方案足以满足我的需求。

        【讨论】:

        • 但是当我在文本字段中输入内容然后,当我尝试向上或向下滚动时,正文内容再次滚动。
        • 你能创建一个 jsfiddle 吗?
        • 添加这个解决了我的问题,即模态窗口内的动态大小的内容不滚动。
        • 很高兴听到这个消息。
        • 这有助于移动用户,尤其是 IOS
        【解决方案9】:

        对此也有疑问,需要在 iPhone + Safari 中添加:

        position: fixed;
        

        正如在其他地方提到的,这造成了滚动到顶部的问题。对我有用的修复是在模态打开时捕获顶部的位置,然后在模态关闭时动画到该位置

        模式打开时:

        scrollTo = $('body').scrollTop();
        $('body').css("position", "fixed");
        

        模式关闭时

        $('body').css("position", "static");
        $('body').animate({scrollTop: scrollTo}, 0);
        

        【讨论】:

        • 也许这是一个更好的选择,因此页面不会向上滚动:$('body').css({"position": "fixed", 'top': (-scrollTo) + 'px'});
        • 修复似乎不起作用。鉴于需要 0 秒动画,当位置设置回静态时会跳转到顶部。
        • 所以,给定一个全局变量var scrollTo;,你可以有两个函数function beforeModalOpen() { scrollTo = $('body').scrollTop(); $('body').css({"position": "fixed", 'top': (-scrollTo) + 'px'}); }function afterModalClose() {$('body').css("position", "static"); $('body').animate({scrollTop: scrollTo}, 0);}并适当地调用它们。
        【解决方案10】:

        我以为您可能忘记将属性data-toggle="modal" 添加到触发模式弹出事件的链接或按钮。首先,我也遇到了同样的问题,但是在添加上面的属性之后,它对我来说效果很好。

        【讨论】:

          【解决方案11】:

          这可能有点像在这里打死马......但是,我目前通过 vanilla JS 在 DIY modals 上实现的解决方案:

          在模态显示上:

          if (document.body.style.position !== 'fixed') {
              document.body.style.top = -window.scrollY + 'px';
              document.body.style.position = 'fixed';
          }
          

          关于模式隐藏:

          document.body.style.position = '';
          window.scrollTo(0, -parseInt(document.body.style.top, 10));
          document.body.style.top = '';
          

          【讨论】:

            【解决方案12】:

            作为@Karthick Kumar answer 的补充,来自bootstrap docs

            show在事件开始时触发

            显示在动作完成时触发

            ...应该是这样的:

            $('.modal')
                .on('show.bs.modal', function (){
                        $('body').css('overflow', 'hidden');
                    })
                .on('hide.bs.modal', function (){
                        // Also if you are using multiple modals (cascade) - additional check
                        if ($('.modal.in').length == 1) {
                            $('body').css('overflow', 'auto');
                        }
                    });
            

            【讨论】:

            • @AntonK hm,我只是简单地提出了对我有用的东西 :) 谢谢你的反对,哈哈
            【解决方案13】:

            大家好,我想我找到了解决办法。目前,这对我在 iphone 和 android 上都有效。它是数小时搜索、阅读和测试的混搭。因此,如果您在这里看到您的部分代码,那就感谢您了,哈哈。

            @media only screen and (max-device-width:768px){
            
            body.modal-open {
            // block scroll for mobile;
            // causes underlying page to jump to top;
            // prevents scrolling on all screens
            overflow: hidden;
            position: fixed;
            }
            }
            
            body.viewport-lg {
            // block scroll for desktop;
            // will not jump to top;
            // will not prevent scroll on mobile
            position: absolute; 
            }
            
            body {  
            overflow-x: hidden;
            overflow-y: scroll !important;
            }
            

            特定媒体出现在桌面上的原因是,当模式打开页面上的所有内容时,我遇到了问题,页面上的所有内容会从居中转移到左侧。看起来像废话。因此,这针对您需要滚动的平板电脑大小的设备。移动设备和平板电脑仍然有轻微的变化,但真的不多。让我知道这是否适合你们。希望这能把钉子钉在棺材里

            【讨论】:

            • 对桌面没有负面影响,确实改善了我的 iPhone 上的模式体验。但是,在关闭我的模式后,原始屏幕滚动到顶部
            • 我正在使用你的解决方案,减去你的代码行position: fixed
            【解决方案14】:

            我找到了一个使用引导模式事件的简单 javascript/jquery 解决方案。

            我的解决方案还修复了 position:fixed 问题,即在打开/关闭模式窗口时,它会将背景页面一直滚动到顶部,而不是保持原位。

            查看详情here

            【讨论】:

              【解决方案15】:

              我知道这个问题已经得到解答,但这些解决方案都不适合我。我需要采取不同的方法。我正在使用 PhoneGap 并且正在本地编译我的代码,所以我不得不将背景移动到正文。我希望这对其他人有帮助。或者,如果有更清洁的方法可以做到这一点,请随时发表评论......

              $(document).on('shown.bs.modal', '.modal', function (e) {
              
                  $("#" + e.target.id).find(".modal-backdrop").css("z-index", $("#" + e.target.id).css("z-index")).insertBefore("#" + e.target.id);
              
              });
              

              【讨论】:

                【解决方案16】:

                使用position:fixed 具有将正文滚动到顶部的副作用。

                如果您不想让身体滚动到顶部,请注意使用position:fixed。如果模态打开,只需禁用 body 上的 touchmove。 注意:模态本身仍然能够在触摸时滚动(如果大于屏幕)。

                CSS:

                body.modal-open {
                    overflow: hidden;
                    width: 100%;
                    /* NO position:fixed here*/
                }
                

                JS:

                $('.modal').on('show.bs.modal', function (ev) { // prevent body from scrolling when modal opens
                    $('body').bind('touchmove', function(e){
                        if (!$(e.target).parents().hasClass( '.modal' )){ //only prevent touch move if it is not the modal
                            e.preventDefault()
                        }
                    })
                })
                $('.modal').on('hide.bs.modal', function (e) { //unbind the touchmove restrictions from body when modal closes
                    $('body').unbind('touchmove');
                })
                

                编辑: 请注意,对于非常小的模态框,您可能需要在 CSS 中添加以下行:

                .modal-dialog{
                    height: 100%;
                }
                

                【讨论】:

                  【解决方案17】:

                  感谢JDiApice,他综合并扩展了iOS 8.x modal scroll issue #14839 上其他贡献者的工作:

                  @media only screen and (max-device-width:768px) {
                  
                  body.modal-open {
                      // block scroll for mobile;
                      // causes underlying page to jump to top;
                      // prevents scrolling on all screens
                      overflow: hidden;
                      position: fixed;
                      }
                  }
                  
                  body.viewport-lg {
                      // block scroll for desktop;
                      // will not jump to top;
                      // will not prevent scroll on mobile
                      position: absolute;
                  }
                  
                  body {
                      overflow-x: hidden;
                      overflow-y: scroll !important;
                  }
                  
                  /* The reason the media specific is on there is 
                     on a desktop i was having issues with when the modal would open 
                     all content on the page would shift from centered to left. 
                     Looked like crap. So this targets up to tablet size devices 
                     where you would need to scroll. There is still a slight shift 
                     on mobile and tablet but its really not much. */
                  

                  与我们尝试的其他解决方案不同,它不会在弹出模式关闭后将背景滚动到顶部。

                  【讨论】:

                    【解决方案18】:

                    我在一个模态之后打开一个模态,发现模态滚动的错误,这个 css 解决了我的问题:

                    .modal {
                        overflow-y: auto;
                        padding-right: 15px;
                    }
                    

                    【讨论】:

                      【解决方案19】:

                      我的解决方案...

                      Ver en jsfiddle

                      //Fix modal mobile Boostrap 3
                      function Show(id){
                          //Fix CSS
                          $(".modal-footer").css({"padding":"19px 20px 20px","margin-top":"15px","text-align":"right","border-top":"1px solid #e5e5e5"});
                          $(".modal-body").css("overflow-y","auto");
                          //Fix .modal-body height
                          $('#'+id).on('shown.bs.modal',function(){
                              $("#"+id+">.modal-dialog>.modal-content>.modal-body").css("height","auto");
                              h1=$("#"+id+">.modal-dialog").height();
                              h2=$(window).height();
                              h3=$("#"+id+">.modal-dialog>.modal-content>.modal-body").height();
                              h4=h2-(h1-h3);      
                              if($(window).width()>=768){
                                  if(h1>h2){
                                      $("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
                                  }
                                  $("#"+id+">.modal-dialog").css("margin","30px auto");
                                  $("#"+id+">.modal-dialog>.modal-content").css("border","1px solid rgba(0,0,0,0.2)");
                                  $("#"+id+">.modal-dialog>.modal-content").css("border-radius",6);               
                                  if($("#"+id+">.modal-dialog").height()+30>h2){
                                      $("#"+id+">.modal-dialog").css("margin-top","0px");
                                      $("#"+id+">.modal-dialog").css("margin-bottom","0px");
                                  }
                              }
                              else{
                                  //Fix full-screen in mobiles
                                  $("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
                                  $("#"+id+">.modal-dialog").css("margin",0);
                                  $("#"+id+">.modal-dialog>.modal-content").css("border",0);
                                  $("#"+id+">.modal-dialog>.modal-content").css("border-radius",0);   
                              }
                              //Aply changes on screen resize (example: mobile orientation)
                              window.onresize=function(){
                                  $("#"+id+">.modal-dialog>.modal-content>.modal-body").css("height","auto");
                                  h1=$("#"+id+">.modal-dialog").height();
                                  h2=$(window).height();
                                  h3=$("#"+id+">.modal-dialog>.modal-content>.modal-body").height();
                                  h4=h2-(h1-h3);
                                  if($(window).width()>=768){
                                      if(h1>h2){
                                          $("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
                                      }
                                      $("#"+id+">.modal-dialog").css("margin","30px auto");
                                      $("#"+id+">.modal-dialog>.modal-content").css("border","1px solid rgba(0,0,0,0.2)");
                                      $("#"+id+">.modal-dialog>.modal-content").css("border-radius",6);               
                                      if($("#"+id+">.modal-dialog").height()+30>h2){
                                          $("#"+id+">.modal-dialog").css("margin-top","0px");
                                          $("#"+id+">.modal-dialog").css("margin-bottom","0px");
                                      }
                                  }
                                  else{
                                      //Fix full-screen in mobiles
                                      $("#"+id+">.modal-dialog>.modal-content>.modal-body").height(h4);
                                      $("#"+id+">.modal-dialog").css("margin",0);
                                      $("#"+id+">.modal-dialog>.modal-content").css("border",0);
                                      $("#"+id+">.modal-dialog>.modal-content").css("border-radius",0);   
                                  }
                              };
                          });  
                          //Free event listener
                          $('#'+id).on('hide.bs.modal',function(){
                              window.onresize=function(){};
                          });  
                          //Mobile haven't scrollbar, so this is touch event scrollbar implementation
                          var y1=0;
                          var y2=0;
                          var div=$("#"+id+">.modal-dialog>.modal-content>.modal-body")[0];
                          div.addEventListener("touchstart",function(event){
                              y1=event.touches[0].clientY;
                          });
                          div.addEventListener("touchmove",function(event){
                              event.preventDefault();
                              y2=event.touches[0].clientY;
                              var limite=div.scrollHeight-div.clientHeight;
                              var diff=div.scrollTop+y1-y2;
                              if(diff<0)diff=0;
                              if(diff>limite)diff=limite;
                              div.scrollTop=diff;
                              y1=y2;
                          });
                          //Fix position modal, scroll to top.    
                          $('html, body').scrollTop(0);
                          //Show
                          $("#"+id).modal('show');
                      }
                      

                      【讨论】:

                      • 我觉得太冗长了。
                      猜你喜欢
                      • 2015-04-15
                      • 2015-10-15
                      • 2018-12-27
                      • 2017-02-28
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-09-11
                      • 2012-03-21
                      相关资源
                      最近更新 更多