ChatGPT解决这个技术问题 Extra ChatGPT

打开模式时防止 BODY 滚动

当我网站上的模态(来自 http://twitter.github.com/bootstrap)打开时,我希望我的身体在使用鼠标滚轮时停止滚动。

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

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

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

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


J
Jeroen

Bootstrap 的 modal 会在显示模式对话框时自动将类 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 部分。


这在引导程序 2.2.2 中不再起作用。希望 .modal-open 将来会回来...... github.com/twitter/bootstrap/issues/5719
@ppetrid 我不希望它回来。根据这篇文章:github.com/twitter/bootstrap/wiki/Upcoming-3.0-changes(查看底部)。引用:“不再有内部模态滚动。相反,模态将增长以容纳其内容,页面滚动以容纳模态。”
@Bagata Cool - modal-open 将在 Bootstrap 3 中返回,因此在启动时删除上述代码应该是安全的。
这就是为什么人们应该继续向下滚动,如果选择的答案不满足你,你有机会找到这样的宝石。没想到一个 97+ 投票的答案被其他不太喜欢的评论埋得如此之深。
这样做的问题是,为了防止文档在打开模式时滚动到顶部,您需要添加 body.modal-open{overflow:visible}。您的解决方案目前有效,缺点是一旦打开模式,文档就会滚动到顶部
C
Community

接受的答案在移动设备上不起作用(至少是带有 Safari 7 的 iOS 7),我不希望当 CSS 可以运行时 MOAR JavaScript 在我的网站上运行。

这个 CSS 将阻止背景页面在模态下滚动:

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

但是,它也有一个轻微的副作用,即基本上滚动到顶部。 position:absolute 解决了这个问题,但重新引入了在移动设备上滚动的功能。

如果您知道您的视口 (my plugin for adding viewport to the <body>),您只需为 position 添加一个 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;
}

this answer is a x-post.


谢谢!手机(至少 iOS 和 Android 原生浏览器)让我头疼,如果没有 position: fixed 就无法工作。
感谢您还包括在显示/隐藏模式时防止页面向左/向右跳转的代码。这非常有用,我验证它解决了我在运行 iOS 9.2.1 的 iPhone 5c 上的 Safari 上遇到的问题。
为了修复滚动到顶部,您可以在添加类之前记录位置,然后在删除类之后,执行 window.scroll 到记录的位置。这就是我为自己修复它的方法:pastebin.com/Vpsz07zd
虽然我觉得这只能满足非常基本的需求,但它是一个有用的修复。谢谢。
以下是我使用 jquery 保留滚动位置的方法:js const currPageScrollPos = $(window).scrollTop() $("body").removeClass("show_overlay") $(window).delay(5).scrollTop(currPageScrollPos)
M
Mehmet Fatih Yıldız

只需隐藏正文溢出,它就会使正文不滚动。隐藏模式时,将其恢复为自动模式。

这是代码:

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

K
Kirk Beard

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

打开模态:

记录正文宽度 将正文溢出设置为隐藏 将正文宽度显式设置为步骤 1 中的值。 var $body = $(document.body); var oldWidth = $body.innerWidth(); $body.css("溢出", "隐藏"); $body.width(oldWidth);

关闭模态:

将正文溢出设置为自动 将正文宽度设置为自动 var $body = $(document.body); $body.css("溢出", "auto"); $body.width("自动");

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


由于缺少更好的术语,我得到了一个“跳跃”的屏幕,而对我来说,关键是遵循宽度设置。万分感谢。
@Hcabnettek 是的:“跳跃”==“文档重排”。很高兴它帮助了你! :-)
有没有一个CSS解决方案?它适用于所有浏览器和移动设备吗?
只是一个错字:在最后一步必须是 $body.css("overflow", "auto"); :)
哦,伙计,多么奇妙的想法。 @jpap 你帮我解决了困扰我很久的文档重排问题。
c
charlietfl

您可以尝试将 body size 设置为 window size with overflow: hidden when modal is open


这样做会在每次打开模式时移动屏幕,不方便,我只需要禁用背景滚动
不确定您是否可以滚动条与浏览器相关,并且您对它们无能为力
您可以将模式设置为“固定”,因此滚动时不会移动
它不是关于阻止模态滚动,而是关于阻止背景中的正文滚动
如果 body 溢出它是滚动的窗口。例如,滚动条不是文档的一部分。
m
merv

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

另一种选择:车轮事件

scroll 事件是不可取消的。但是,可以取消 mousewheelwheel 事件。最大的警告是并非所有旧版浏览器都支持它们,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


您的 JSFiddle 不适用于 Firefox 24、Chrome 24 和 IE9。
@AxeEffect 现在应该可以工作了。唯一的问题是对 Bootstrap 库的外部引用已更改。感谢您的提醒。
这不会阻止触摸设备滚动,overflow:hidden 现在更好。
它们都在工作,但不适用于移动设备。 -__- 经过测试的 Android 4.1 和 Chrome
@TowerJimmy,您可能需要为此取消触摸或拖动事件(如果可能的话)
f
fatCop

试试这个:

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

它对我有用。 (支持 IE8)


这很有效,但也会导致您在使用 position: fixed 打开模式时跳转到顶部。
j
jparkerweb
/* =============================
 * 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(); });
});

t
tetsuo

仅通过更改 CSS 无法使其在 Chrome 上运行,因为我不希望页面滚动回顶部。这很好用:

$("#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.2 上对我有用的唯一解决方案。
有角材料sidenavs的跳转到顶部问题。这是似乎在所有情况下都有效的唯一答案(桌面/移动+允许在模态/sidenav中滚动+保持正文滚动位置固定而不跳跃)。
这也是唯一对我有用的解决方案。发送
J
Jassim Abdul Latheef

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

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

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

这绝对是正确的答案,因为普遍的共识答案会将页面滚动到顶部,这是一种可怕的用户体验。你应该为此写一篇博客。我最终把它变成了一个全球性的解决方案。
非常简单和正确的答案。 2020年解决了我的问题。
u
user1095118

截至 2017 年 11 月,Chrome 引入了一个新的 CSS 属性

overscroll-behavior: contain;

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

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

https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior

https://developers.google.com/web/updates/2017/11/overscroll-behavior


即使在 2020 年,caniuse 对此的支持率也只有 78%。几乎没有可行的解决方案。
2022 年似乎会好转:caniuse.com/?search=overscroll-behavior
M
Murat Yıldız

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

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

希望这可以帮助...


A
Anish Gupta

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

在 jQuery 中:

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

正如我之前所说,我不是 100% 确定,但还是试试吧。


这不会阻止正文在打开模式时滚动
@xorinzor 您在 charlietfl 的回答的评论部分中说这有效。但是您说:这不会阻止在打开模式时正文滚动。
是的,但目前它是唯一部分有效的解决方案,我很好。我将他的回复标记为答案的原因是因为他更早地给出了答案。
@xorinzor 真的,我以为我在他/她之前回答了,可能是一些奇怪的故障。不过很好
A
AdamJB

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

要停止页面跳转到顶部并防止内容右移,请在触发模式时向 body 添加一个类并设置以下 CSS 规则:

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

position:staticheight:auto 结合起来阻止内容向右跳转。 overflow-y:hidden; 阻止页面在模式后面滚动。


S
Stephen M. Harris

最好的解决方案是大多数这些答案使用的纯 css 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');
}

查看 this jsFiddle 以查看它的使用情况。


这不是那么旧,但这些对我来说根本不起作用,即使是我仍然可以滚动窗口的小提琴,我错过了什么?
打开和关闭模态几次,主绿色的DIV就缩小了!
@Webinan 我在 Win7 上的 Chrome 中没有看到这个。您的浏览器和视口大小是多少?
@smhmic 在大约 20 次打开和关闭后,绿色 div 的宽度变得等于 open modal 按钮的宽度。镀铬 8
类似于@jpap 的答案 (stackoverflow.com/a/16451821/5516499),但添加了错误。 :-(
A
Aravind Siruvuru

反应,如果你正在寻找

正在弹出的模态中的 useEffect

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

D
Danie

许多人建议在正文上使用“溢出:隐藏”,这不起作用(至少在我的情况下不是),因为它会使网站滚动到顶部。

这是适用于我的解决方案(在手机和电脑上),使用 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');
    });

这将使模态的滚动起作用,并防止网站同时滚动。


看起来这个解决方案也修复了这个 iOS 错误:hackernoon.com/…
f
freedude

我必须设置视口高度才能使其完美运行

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

m
myriacl

您可以使用以下逻辑,我对其进行了测试并且可以正常工作(即使在 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>

l
ling

基于这个小提琴: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');

不应该将 overflow 设置为 hidden 吗? +1 虽然这对我有用(使用 hidden)。
L
Leigh

可悲的是,上面的答案都没有解决我的问题。

在我的情况下,网页最初有一个滚动条。每当我单击模式时,滚动条都不会消失,并且标题会向右移动一点。

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

https://i.stack.imgur.com/qZa3y.png

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

https://i.stack.imgur.com/AzzuA.png

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


G
Gerhard Liebenberg

这对我有用:

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

在上述所有答案中,这是第一个也是唯一一个对我有用的答案。
e
evoskuil

大多数作品都在这里,但我没有看到任何将它们放在一起的答案。

问题是三方面的。

(1)防止底层页面的滚动

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

(2)并去掉滚动条

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

(3) modal 被dismiss时的清理

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

如果模态不是全屏,则将 .modal 绑定应用于全屏覆盖。


这也可以防止在模态中滚动。
同样的问题。你找到解决办法了吗? @丹尼尔
@Vay 有点。看看这个:blog.christoffer.me/…
p
pierrea

我对 Bootstrap 3 的解决方案:

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

因为对我来说,body.modal-open 类中唯一的 overflow: hidden 并没有阻止页面由于原始 margin-right: 15px 而向左移动。


C
Cliff

我就是这样弄的...

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

但是当滚动条消失时,它把所有东西都向右移动了 20 像素,所以我添加了

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

紧随其后。

为我工作。


这仅在模式小于屏幕尺寸时才有效。
M
Mats

如果模式是 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); 
});

L
Lozhachevskaya Anastasiya

我有一个由复选框 hack 生成的侧边栏。但主要思想是保存文档 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); } }); }) });


L
LowFieldTheory

因为对我来说这个问题主要出现在 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;
    });
  }

C
Community

以上答案都不适合我。所以我找到了另一种效果很好的方法。

只需添加一个 scroll.(namespace) 侦听器并将 documentscrollTop 设置为它的最新值...

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

// 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 上效果不佳。有什么建议可以解决吗?


这是我想出的更好的变体。但是,唉,我也遇到了 Chrome 的问题。由于奇怪且不可预测的副作用,它仍然存在问题
L
Leo

这有效

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

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅