【发布时间】:2013-09-27 21:25:47
【问题描述】:
在移动平台上打开 Bootstrap 3 modal 时如何防止背景滚动?在桌面浏览器上,背景被阻止滚动并正常工作。
在移动浏览器(Safari ios、Chrome ios 等)上,当打开模态并使用手指滚动它时,背景也会像模态一样滚动。我该如何预防?
【问题讨论】:
标签: html twitter-bootstrap modal-dialog twitter-bootstrap-3
在移动平台上打开 Bootstrap 3 modal 时如何防止背景滚动?在桌面浏览器上,背景被阻止滚动并正常工作。
在移动浏览器(Safari ios、Chrome ios 等)上,当打开模态并使用手指滚动它时,背景也会像模态一样滚动。我该如何预防?
【问题讨论】:
标签: html twitter-bootstrap modal-dialog twitter-bootstrap-3
请看这里:https://github.com/twbs/bootstrap/issues/7501
那就试试吧:
$('body').css('overflow','hidden');
$('body').css('position','fixed');
V3.0.0。应该已经解决了这个问题。你用的是最新版本吗?如果是这样,请在https://github.com/twbs/bootstrap/ 上发布问题
【讨论】:
body.modal-open { position: fixed; } 有滚动到顶部的副作用...... (仍然不确定什么是最好的方法)
试试这个,
body.modal-open {
overflow: hidden;
position:fixed;
width: 100%;
}
【讨论】:
我尝试了接受的答案,该答案阻止了正文滚动,但出现了滚动到顶部的问题。这应该可以解决这两个问题。
附带说明,它似乎溢出:隐藏在 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);
});
【讨论】:
$('.modal')
.on('shown', function(){
console.log('show');
$('body').css({overflow: 'hidden'});
})
.on('hidden', function(){
$('body').css({overflow: ''});
});
用这个
【讨论】:
不需要脚本。
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;
}
}
}
}
【讨论】:
选择的解决方案有效,但它们也会将背景捕捉到顶部滚动位置。我扩展了上面的代码来修复那个“跳转”。
//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;
}
【讨论】:
$('body').scrollTop(lastKnownScrollTopPosition); 也添加到我的 x.js.erb 文件(提交时执行 js 代码的文件)效果很好。谢谢!
如果你使用 jQuery,你可以使用 scrollTop 来做到这一点
#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);
});
【讨论】:
以上答案没有帮助,所以我所做的是:
.modal {
-webkit-overflow-scrolling: touch;
}
我的特殊问题是加载后增加了模态大小。
这是一个已知的 iOS 问题,see here。由于它不会破坏其他任何东西,因此上述解决方案足以满足我的需求。
【讨论】:
对此也有疑问,需要在 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'});
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);}并适当地调用它们。
我以为您可能忘记将属性data-toggle="modal" 添加到触发模式弹出事件的链接或按钮。首先,我也遇到了同样的问题,但是在添加上面的属性之后,它对我来说效果很好。
【讨论】:
这可能有点像在这里打死马......但是,我目前通过 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 = '';
【讨论】:
作为@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');
}
});
【讨论】:
大家好,我想我找到了解决办法。目前,这对我在 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;
}
特定媒体出现在桌面上的原因是,当模式打开页面上的所有内容时,我遇到了问题,页面上的所有内容会从居中转移到左侧。看起来像废话。因此,这针对您需要滚动的平板电脑大小的设备。移动设备和平板电脑仍然有轻微的变化,但真的不多。让我知道这是否适合你们。希望这能把钉子钉在棺材里
【讨论】:
position: fixed
我找到了一个使用引导模式事件的简单 javascript/jquery 解决方案。
我的解决方案还修复了 position:fixed 问题,即在打开/关闭模式窗口时,它会将背景页面一直滚动到顶部,而不是保持原位。
查看详情here
【讨论】:
我知道这个问题已经得到解答,但这些解决方案都不适合我。我需要采取不同的方法。我正在使用 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);
});
【讨论】:
使用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%;
}
【讨论】:
感谢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. */
与我们尝试的其他解决方案不同,它不会在弹出模式关闭后将背景滚动到顶部。
【讨论】:
我在一个模态之后打开一个模态,发现模态滚动的错误,这个 css 解决了我的问题:
.modal {
overflow-y: auto;
padding-right: 15px;
}
【讨论】:
我的解决方案...
//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');
}
【讨论】: