我想让我的身体在使用鼠标滚轮时停止滚动,而我的网站上的Modal(来自http://twitter.github.com/bootstrap)是打开的。

当模式被打开时,我试图调用下面的javascript片段,但没有成功

$(window).scroll(function() { return false; });

AND

$(window).live('scroll', function() { return false; });

请注意,我们的网站放弃了对IE6的支持,IE7+需要兼容。


你可以试着设置body size为window size, overflow:当modal打开时隐藏


我对这段代码不太确定,但值得一试。

jQuery:

$(document).ready(function() {
    $(/* Put in your "onModalDisplay" here */)./* whatever */(function() {
        $("#Modal").css("overflow", "hidden");
    });
});

就像我之前说过的,我不是百分百确定,但还是试一试吧。


你可以使用下面的逻辑,我测试了它,它可以工作(即使在IE中)

   <html>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">

var currentScroll=0;
function lockscroll(){
    $(window).scrollTop(currentScroll);
}


$(function(){

        $('#locker').click(function(){
            currentScroll=$(window).scrollTop();
            $(window).bind('scroll',lockscroll);

        })  


        $('#unlocker').click(function(){
            currentScroll=$(window).scrollTop();
            $(window).unbind('scroll');

        })
})

</script>

<div>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button id="locker">lock</button>
<button id="unlocker">unlock</button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

</div>

Bootstrap的模态在模态对话框显示时自动将类modal-open添加到主体,并在对话框隐藏时将其删除。因此,您可以在CSS中添加以下内容:

body.modal-open {
    overflow: hidden;
}

你可能会说上面的代码属于Bootstrap CSS代码库,但这是一个简单的修复,可以将它添加到你的网站。

2013年2月8日更新 这在Twitter Bootstrap v. 2.3.0中已经停止工作——他们不再向主体添加modal-open类。

一个变通的方法是在模态即将显示时将类添加到主体中,并在模态关闭时将其删除:

$("#myModal").on("show", function () {
  $("body").addClass("modal-open");
}).on("hidden", function () {
  $("body").removeClass("modal-open")
});

2013年3月11日更新 看起来modal-open类将在Bootstrap 3.0中返回,显式地用于防止滚动:

在body上重新引入。modal-open(这样我们就可以把滚动移到这里)

看这个:https://github.com/twitter/bootstrap/pull/6342 -看Modal部分。


简单地隐藏身体溢出,它使身体不滚动。隐藏模式时,将其恢复为自动模式。

代码如下:

$('#adminModal').modal().on('shown', function(){
    $('body').css('overflow', 'hidden');
}).on('hidden', function(){
    $('body').css('overflow', 'auto');
})

警告:下面的选项与Bootstrap v3.0无关。X,因为在这些版本中滚动被显式地限制在模态本身。如果禁用轮事件,可能会无意中阻止一些用户在高度大于视口高度的模态中查看内容。


还有另一个选择:车轮事件

滚动事件不可取消。但是,可以取消鼠标滚轮和滚轮事件。需要注意的是,并不是所有的传统浏览器都支持它们,Mozilla最近才在Gecko 17.0中添加了对后者的支持。我不知道它们的全部分布,但IE6+和Chrome确实支持它们。

下面是如何利用它们的方法:

$('#myModal')
  .on('shown', function () {
    $('body').on('wheel.modal mousewheel.modal', function () {
      return false;
    });
  })
  .on('hidden', function () {
    $('body').off('wheel.modal mousewheel.modal');
  });

JSFiddle


这招对我很管用:

$("#mymodal").mouseenter(function(){
   $("body").css("overflow", "hidden"); 
}).mouseleave(function(){
   $("body").css("overflow", "visible");
});

您需要超越@charlietfl的答案并考虑滚动条,否则您可能会看到一个文档回流。

打开模式:

记录身体宽度 将正文溢出设置为隐藏 显式地将主体宽度设置为步骤1中的宽度。 Var $body = $(document.body); var oldWidth = $body.innerWidth(); 美元body.css(“溢出”,“隐藏”); 美元body.width (oldWidth);

关闭模态:

将body overflow设置为auto 将车身宽度设置为auto Var $body = $(document.body); 美元body.css(“溢出”,“汽车”); 美元body.width(“自动”);

灵感来源:http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php


/* =============================
 * Disable / Enable Page Scroll
 * when Bootstrap Modals are
 * shown / hidden
 * ============================= */

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
      e.preventDefault();
  e.returnValue = false;  
}

function theMouseWheel(e) {
  preventDefault(e);
}

function disable_scroll() {
  if (window.addEventListener) {
      window.addEventListener('DOMMouseScroll', theMouseWheel, false);
  }
  window.onmousewheel = document.onmousewheel = theMouseWheel;
}

function enable_scroll() {
    if (window.removeEventListener) {
        window.removeEventListener('DOMMouseScroll', theMouseWheel, false);
    }
    window.onmousewheel = document.onmousewheel = null;  
}

$(function () {
  // disable page scrolling when modal is shown
  $(".modal").on('show', function () { disable_scroll(); });
  // enable page scrolling when modal is hidden
  $(".modal").on('hide', function () { enable_scroll(); });
});

HTML:

<body onscroll="stop_scroll()">

javascript:

function stop_scroll(){
    scroll(0,0) ;
}

如果你在stop_scroll()中设置了一个标记(bool),你可以决定什么时候使用它(如果你只是暂时需要它)。

这将重置滚动每当某些元素溢出主体边界和窗口倾向于滚动(这是完全独立于滚动条;溢出:隐藏与此无关)。


最好的解决方案是大多数答案所使用的css-only body{overflow:hidden}解决方案。一些答案提供了一个修复,也防止“跳跃”造成的消失滚动条;然而,没有一个太优雅。我写了这两个函数,它们看起来工作得很好。

var $body = $(window.document.body);

function bodyFreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('overflow', 'hidden');
    $body.css('marginRight', ($body.css('marginRight') ? '+=' : '') + ($body.innerWidth() - bodyWidth))
}

function bodyUnfreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('marginRight', '-=' + (bodyWidth - $body.innerWidth()))
    $body.css('overflow', 'auto');
}

查看jsFiddle的使用情况。


大部分的片段都在这里,但我没有看到任何答案把它们放在一起。

这个问题有三个方面。

(1)防止底层页面滚动

$('body').css('overflow', 'hidden')

(2)并移除滚动条

var handler = function (e) { e.preventDefault() }
$('.modal').bind('mousewheel touchmove', handler)

(3)模态解散时进行清理

$('.modal').unbind('mousewheel touchmove', handler)
$('body').css('overflow', '')

如果模式不是全屏,那么将.modal绑定应用到全屏覆盖。


不能让它在Chrome上工作,只是通过改变CSS,因为我不想让页面滚动回顶部。这很有效:

$("#myModal").on("show.bs.modal", function () {
  var top = $("body").scrollTop(); $("body").css('position','fixed').css('overflow','hidden').css('top',-top).css('width','100%').css('height',top+5000);
}).on("hide.bs.modal", function () {
  var top = $("body").position().top; $("body").css('position','relative').css('overflow','auto').css('top',0).scrollTop(-top);
});

我对Bootstrap 3的解决方案:

.modal {
  overflow-y: hidden;
}
body.modal-open {
  margin-right: 0;
}

因为对我来说唯一的溢出:隐藏在身上。模态打开类并没有阻止页面向左移动,因为原始的右距:15px。


对于那些想知道如何获得滚动事件的引导3模态:

$(".modal").scroll(function() {
    console.log("scrolling!);
});

接受的答案不工作在手机上(iOS 7 w/ Safari 7,至少),我不希望MOAR JavaScript运行在我的网站上,当CSS将做。

这个CSS将阻止后台页面在模式下滚动:

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

然而,它也有一个轻微的副作用,基本上是滚动到顶部。位置:绝对解决了这个问题,但是,重新引入了在移动设备上滚动的能力。

如果你知道你的视口(我的插件为<body>添加视口),你可以为这个位置添加一个css切换。

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 {
    // STOP MOVING AROUND!
    overflow-x: hidden;
    overflow-y: scroll !important;
}

这个答案是x-post。


这对我来说是最好的解决方案:

Css:

.modal {
     overflow-y: auto !important;
}

Js:

modalShown = function () {
    $('body').css('overflow', 'hidden');
},

modalHidden = function () {
    $('body').css('overflow', 'auto');
}

我使用这个香草js函数添加“模态打开”类的身体。(根据smhmic的回答)

function freezeScroll(show, new_width)
{
    var innerWidth = window.innerWidth,
        clientWidth = document.documentElement.clientWidth,
        new_margin = ((show) ? (new_width + innerWidth - clientWidth) : new_width) + "px";

    document.body.style.marginRight = new_margin;
    document.body.className = (show) ? "modal-open" : "";
};

隐藏溢出和固定位置的技巧,但在我的流体设计中,它会固定它超过浏览器宽度,所以宽度:100%固定。

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

试试下面的代码:

$('.entry_details').dialog({
    width:800,
    height:500,
    draggable: true,
    title: entry.short_description,
    closeText: "Zamknij",
    open: function(){
        //    blokowanie scrolla dla body
        var body_scroll = $(window).scrollTop();
        $(window).on('scroll', function(){
            $(document).scrollTop(body_scroll);
        });
    },
    close: function(){
        $(window).off('scroll');
    }
}); 

试试这个:

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

这对我很管用。(支持IE8)


我刚才是这样做的……

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

但当滚轮消失时,它将所有东西都正确移动了20px,所以我添加了

$('body').css('margin-right', '20px');

就在后面。

对我有用。


这个问题已经解决, 解决方案:只需打开bootstrap .css并按以下方式更改

body.modal-open,
.modal-open .navbar-fixed-top,
.modal-open .navbar-fixed-bottom {
  margin-right: 15px;
}

to

 body.modal-open,
.modal-open .navbar-fixed-top,
.modal-open .navbar-fixed-bottom {
  /*margin-right: 15px;*/
}

请查看下面的youtube视频,只有不到3分钟,你的问题将解决… https://www.youtube.com/watch?v=kX7wPNMob_E


我不是100%确定这将与Bootstrap一起工作,但值得一试-它与momodar .js一起工作,可以在github上找到:http://vodkabears.github.io/remodal/,它将有意义的方法非常相似。

为了阻止页面跳转到顶部,也防止内容右移,在模态触发时向主体添加一个类,并设置以下CSS规则:

body.with-modal {
    position: static;
    height: auto;
    overflow-y: hidden;
}

位置:静态和高度:自动结合起来阻止内容向右跳转。overflow-y:隐藏;停止页面在模态后面可滚动。


您应该在HTML中添加overflow:隐藏以获得更好的跨平台性能。

我会用

html.no-scroll {
    overflow: hidden;
}

   $('.modal').on('shown.bs.modal', function (e) {
      $('body').css('overflow-y', 'hidden');
   });
   $('.modal').on('hidden.bs.modal', function (e) {
      $('body').css('overflow-y', '');
   });

如果modal的高度/宽度为100%,“mouseenter/leave”可以很容易地启用/禁用滚动。这对我来说真的很管用:

var currentScroll=0;
function lockscroll(){
    $(window).scrollTop(currentScroll);
} 
$("#myModal").mouseenter(function(){
    currentScroll=$(window).scrollTop();
    $(window).bind('scroll',lockscroll); 
}).mouseleave(function(){
    currentScroll=$(window).scrollTop();
    $(window).unbind('scroll',lockscroll); 
});

基于此提琴:http://jsfiddle.net/dh834zgw/1/

下面的代码片段(使用jquery)将禁用窗口滚动:

 var curScrollTop = $(window).scrollTop();
 $('html').toggleClass('noscroll').css('top', '-' + curScrollTop + 'px');

在你的css中:

html.noscroll{
    position: fixed;
    width: 100%;
    top:0;
    left: 0;
    height: 100%;
    overflow-y: scroll !important;
    z-index: 10;
 }

现在,当你删除模态时,不要忘记删除html标签上的noscroll类:

$('html').toggleClass('noscroll');

添加类'is-modal-open'或用javascript修改body标签的样式都是可以的,它会像预期的那样工作。但我们要面对的问题是当body变成overflow:hidden时,它会跳到顶部(scrollTop将变成0)。这将在以后成为一个可用性问题。

作为这个问题的解决方案,而不是改变正文标签溢出:隐藏改变它在html标签

$('#myModal').on('shown.bs.modal', function () {
  $('html').css('overflow','hidden');
}).on('hidden.bs.modal', function() {
  $('html').css('overflow','auto');
});

对于Bootstrap,你可以尝试这样做(在Firefox, Chrome和Microsoft Edge上工作):

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

对于那些使用SharePoint 2013的人,有一个小提示。主体已经有overflow: hidden。你要找的是设置overflow:隐藏在id为s4-workspace的div元素上,例如。

var body = document.getElementById('s4-workspace');
body.className = body.className+" modal-open";

我有一个边栏,是由复选框黑客生成的。 但主要思想是保存文档scrollTop,而不是在滚动窗口期间更改它。

我只是不喜欢页面跳转时,身体变成'溢出:隐藏'。

window.addEventListener('load', function() { let prevScrollTop = 0; let isSidebarVisible = false; document.getElementById('f-overlay-chkbx').addEventListener('change', (event) => { prevScrollTop = window.pageYOffset || document.documentElement.scrollTop; isSidebarVisible = event.target.checked; window.addEventListener('scroll', (event) => { if (isSidebarVisible) { window.scrollTo(0, prevScrollTop); } }); }) });


为我工作

$('#myModal').on({'mousewheel': function(e) 
    {
    if (e.target.id == 'el') return;
    e.preventDefault();
    e.stopPropagation();
   }
});

不幸的是,上面的答案没有一个能解决我的问题。

在我的情况下,网页原本有一个滚动条。每当我点击模态,滚动条不会消失,标题会向右移动一点。

然后我尝试添加.modal-open{overflow:auto;}(大多数人都推荐)。它确实解决了问题:滚动条出现后,我打开模式。然而,另一个副作用出现了,那就是“标题下面的背景会向左移动一点,在模态后面还有一个长条”

幸运的是,在添加{padding-right: 0 !important;}之后,一切都被完美地修复了。标题和正文背景都没有移动,模态仍然保持滚动条。

希望这可以帮助那些仍然被这个问题困扰的人。好运!


当你在另一个模态中使用一个模态时,就会发生上述情况。当我在另一个模态中打开一个模态时,后者的关闭将从主体中移除类modal-open。这个问题的解决取决于你如何关闭后一个模式。

如果你用html关闭模态,

<button type="button" class="btn" data-dismiss="modal">Close</button>

然后你必须像这样添加一个监听器,

$(modalSelector).on("hidden.bs.modal", function (event) {
    event.stopPropagation();
    $("body").addClass("modal-open");
    return false;
});

如果你用javascript关闭模态,

$(modalSelector).modal("hide");

然后你必须在一段时间后像这样运行命令,

setInterval(function(){$("body").addClass("modal-open");}, 300);

许多人建议在正文上使用“overflow: hidden”,这是行不通的(至少在我的情况下不是),因为它会让网站滚动到顶部。

这是适用于我的解决方案(手机和电脑),使用jQuery:

    $('.yourModalDiv').bind('mouseenter touchstart', function(e) {
        var current = $(window).scrollTop();
        $(window).scroll(function(event) {
            $(window).scrollTop(current);
        });
    });
    $('.yourModalDiv').bind('mouseleave touchend', function(e) {
        $(window).off('scroll');
    });

这将使模式的滚动工作,并防止网站在同一时间滚动。


2017年11月Chrome引入了一个新的css属性

overscroll-behavior:包含;

这解决了这个问题,尽管在编写时跨浏览器支持有限。

有关详细信息和浏览器支持,请参阅下面的链接

https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior https://developers.google.com/web/updates/2017/11/overscroll-behavior


为什么不像布尔玛那样做呢? 当modal is-active时,将它们的类.is-clipped添加到html中,即overflow: hidden!important; 就是这样。

编辑:好的,Bulma有这个bug,所以你必须添加其他东西,比如

html.is-modal-active {
  overflow: hidden !important;
  position: fixed;
  width: 100%; 
}

因为对我来说,这个问题主要出现在iOS上,所以我提供了只在iOS上修复的代码:

  if(!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) {
    var $modalRep    = $('#modal-id'),
        startScrollY = null, 
        moveDiv;  

    $modalRep.on('touchmove', function(ev) {
      ev.preventDefault();
      moveDiv = startScrollY - ev.touches[0].clientY;
      startScrollY = ev.touches[0].clientY;
      var el = $(ev.target).parents('#div-that-scrolls');
      // #div-that-scrolls is a child of #modal-id
      el.scrollTop(el.scrollTop() + moveDiv);
    });

    $modalRep.on('touchstart', function(ev) {
      startScrollY = ev.touches[0].clientY;
    });
  }

在StackOverflow上做了8-10个小时的研究后,我找到了一个可行的解决方案。

突破

$('.modal').is(':visible');

因此,我已经构建了一个函数来检查是否有任何模态是打开的,它将定期添加类*modal-open**到

 setInterval(function()
     {
         if($('.modal').is(':visible')===true)
         {
             $("body").addClass("modal-open");
         }
         else
         {
             $("body").removeClass("modal-open");
         }

     },200);

这里使用$(".modal")的原因是所有的模态(在Bootstrap中)都使用类modal (fade/show是根据状态而定)

所以我的模态现在运行完美没有身体得到滚动。

这在GitHub中也是一个bug/闻所未闻的问题,但没有人打扰。


以上的答案都不适合我。所以我找到了另一种行之有效的方法。

只需添加一个scroll.(命名空间)监听器,并将文档的scrollTop设置为它的最新值…

并在关闭脚本中删除侦听器。

// in case of bootstrap modal example:
$('#myModal').on('shown.bs.modal', function () {
  
  var documentScrollTop = $(document).scrollTop();
  $(document).on('scroll.noScroll', function() {
     $(document).scrollTop(documentScrollTop);
     return false;
  });

}).on('hidden.bs.modal', function() {

  $(document).off('scroll.noScroll');

});

更新

似乎,这不是很好地工作在chrome。有什么建议吗?


这是

body.modal-open {
   overflow: hidden !important;
}

这是我的香草JS解决方案基于@jpap jquery:

let bodyElement = document.getElementsByTagName('body')[0];

// lock body scroll
    let width = bodyElement.scrollWidth;
    bodyElement.classList.add('overflow-hidden');
    bodyElement.style.width = width + 'px';

// unlock body scroll
    bodyElement.classList.remove('overflow-hidden');
    bodyElement.style.width = 'auto';

反应,如果你在寻找

正在弹出的模态中的useEffect

 useEffect(() => {
    document.body.style.overflowY = 'hidden';
    return () =>{
      document.body.style.overflowY = 'auto';
    }
  }, [])

我必须设置视口高度才能让它完美工作

body.modal-open {
  height: 100vh;
  overflow: hidden;
}

下面是我在React中修复这个问题的方法:

useEffect(() => {
  if (isShown) {
    const width = document.body.clientWidth;
    document.body.style.overflow = "hidden";
    document.body.style.width = `${width}px`;
  } else {
    document.body.style.overflow = "visible";
    document.body.style.width = `auto`;
  }

  return () => {
    document.body.style.overflow = "visible";
    document.body.style.width = `auto`;
  };
}, [isShown]);

我读的大多数答案都是关于React的。

我的React功能组件的最佳解决方案是使用@arcticmatt最初提供的解决方案

我在下面的代码示例中包含了一些在其他答案中提到的改进(注意useEffect定义):

import {useEffect, useRef} from "react";

export default function PopoverMenu({className, handleClose, children}) {
  const selfRef = useRef(undefined);

  useEffect(() => {
    const isPopoverOpenned = selfRef.current?.style.display !== "none";
    const focusedElement = document?.activeElement;
    const scrollPosition = {x: window.scrollX, y: window.scrollY};
    if (isPopoverOpenned) {
      preventDocBodyScrolling();
    } else {
      restoreDocBodyScrolling();
    }

    function preventDocBodyScrolling() {
      const width = document.body.clientWidth;
      const hasVerticalScrollBar = (window.innerWidth > document.documentElement.clientWidth);
      document.body.style.overflowX = "hidden";
      document.body.style.overflowY = hasVerticalScrollBar ? "scroll" : "";
      document.body.style.width = `${width}px`;
      document.body.style.position = "fixed";

    }

    function restoreDocBodyScrolling() {
      document.body.style.overflowX = "";
      document.body.style.overflowY = "";
      document.body.style.width = "";
      document.body.style.position = "";
      focusedElement?.focus();
      window.scrollTo(scrollPosition.x, scrollPosition.y);
    }


    return () => {
      restoreDocBodyScrolling(); // cleanup on unmount
    };
  }, []);

  return (
    <>
      <div
        className="backdrop"
        onClick={() => handleClose && handleClose()}
      />
      <div
        className={`pop-over-menu${className ? (` ${className}`) : ""}`}
        ref={selfRef}
      >
        <button
          className="pop-over-menu--close-button" type="button"
          onClick={() => handleClose && handleClose()}
        >
          X
        </button>
        {children}
      </div>
    </>
  );
}


这个解决方案对我很有效:

var scrollDistance = 0; $(document).on("show.bs.modal", ".modal", function () { scrollDistance = $(window).scrollTop(); $("body").css("top", scrollDistance * -1); }); $(document).on("hidden.bs.modal", ".modal", function () { $("body").css("top", ""); $(window).scrollTop(scrollDistance); }); .content-area { height: 750px; background: grey; text-align: center; padding: 25px; font-weight:700; font-size: 30px; } body.modal-open { position: fixed; left: 0; width: 100%; } <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/> <script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script> <div class="content-area"> Scroll Down To Modal Button<br/> <svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" fill="currentColor" class="bi bi-arrow-down" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z"/> </svg> </div> <center class="my-3"> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal"> Launch demo modal </button> </center> <div class="content-area"></div> <!-- Modal --> <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">Modal title</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> <p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p> <p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div> </div> </div>

基本上,当打开模态时,它会为主体添加一个负顶部,以在打开模态之前保持窗口滚动位置。关闭模态时,窗口滚动保持使用相同的值应用于顶部时,打开。 这种方法可以防止身体滚动。

这是一把能用的小提琴


现在是2022年,现在有了更好的CSS解决方案。这很有效。当模式打开时,您可以将这个类添加到body元素中,或者修改body样式本身。

  .body-no-scroll {
    height: 100vh;
    width: 100vw;
    touch-action: none;
    -webkit-overflow-scrolling: none;
    overflow: hidden;
    overscroll-behavior: none;
  }

最著名的答案很简单,即。

body{
   height: 100%;
   overflow-y: hidden;
}

但是,如果你想在子/孙子中打开一个模态并停止滚动,该如何解决呢?更长期的解决方案是使用props或存储在Angular/React中,并改变body标签的高度和溢出属性。

另一种解决方案是从子/孙子组件获取主体,并相应地改变其高度和溢出以停止滚动。 在我的例子中,我只是这样做的

if(isModalExpanded){
    document.body.style.overflow = "hidden";
    document.body.style.height = "100%";
}
else{
    document.body.style.overflow = "auto";
    document.body.style.height = "auto";
}

这是TypeScript中的一种解决方案,可以轻松地阻止事件扩展,也可以处理移动设备。当禁用垂直滚动条时,这也不会导致水平跳转。 只需使用底部的导出函数,例如任何HTML元素上的onclick处理程序。如果不是在NodeJS环境中运行,只需删除该进程。客户端检查。

/**
 * Handles scroll events for modal content
 */

const events = [
  'DOMMouseScroll',
  'mousewheel',
  'wheel',
  'touchmove',
  'keydown',
  'mousedown',
  'scroll',
];

const preventDefault = (e: Event) => {
  e.preventDefault();
  e.stopPropagation();
  return false;
};

let currentY: number;

const disableScroll = () => {
  currentY = window.scrollY;

  events.forEach((event) => {
    window.addEventListener(event, preventDefault, {
      passive: false,
    });
  });

  const bodyStyle = document.body.style;
  bodyStyle.setProperty('touch-action', 'none');
  bodyStyle.setProperty('position', 'fixed');
  bodyStyle.setProperty('overflow-y', 'scroll');
  bodyStyle.setProperty('width', '100%');
  bodyStyle.setProperty('top', `-${currentY}px`);
};

const enableScroll = () => {
  events.forEach((event) => {
    window.removeEventListener(event, preventDefault);
  });

  const bodyStyle = document.body.style;
  bodyStyle.removeProperty('touch-action');
  bodyStyle.removeProperty('position');
  bodyStyle.removeProperty('overflow-y');
  bodyStyle.removeProperty('width');
  bodyStyle.removeProperty('top');
  window.scroll(0, currentY);
};

/**
 * Makes a component (e.g. popup) modal
 */
export const makeModal = () => {
  if (process.client) {
    disableScroll();
  }
};

/**
 * Makes a component (e.g. popup) non-modal
 */
export const makeNonModal = () => {
  if (process.client) {
    enableScroll();
  }
};


我发现这是最好的解决方案:

   export const removeBodyScrollingWhenModalOpen = (modalOpen: boolean) => {
        console.log('modalOpen: ', modalOpen);
        const body = document.body;
        if (modalOpen && isMobile()) {
            const scrollY = document.documentElement.style.getPropertyValue('--scroll-y');
            body.style.position = 'fixed';
            body.style.top = `-${scrollY}`;
        } else if (!modalOpen && isMobile()) {
            const scrollY = body.style.top;
            body.style.position = '';
            body.style.top = '';
            window.scrollTo(0, parseInt(scrollY || '0') * -1);
        } else if (modalOpen) {
            document.body.style.overflowY = 'hidden';
        } else {
            document.body.style.overflowY = 'visible';
        }
    };