Prevent BODY from scrolling when a modal is opened
The accepted answer doesn't work on mobile (iOS 7 w/ Safari 7, at least) and I don't want MOAR JavaScript running on my site when CSS will do.
This CSS will prevent the background page from scrolling under the modal:
body.modal-open {
overflow: hidden;
position: fixed;
}
However, it also has a slight side-affect of essentially scrolling to the top. position:absolute
resolves this but, re-introduces the ability to scroll on mobile.
If you know your viewport (my plugin for adding viewport to the <body>
) you can just add a css toggle for the position
.
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;
}
I also add this to prevent the underlying page from jumping left/right when showing/hiding modals.
body {
// STOP MOVING AROUND!
overflow-x: hidden;
overflow-y: scroll !important;
}
this answer is a x-post.
You need to go beyond @charlietfl's answer and account for scrollbars, otherwise you may see a document reflow.
Opening the modal:
- Record the
body
width - Set
body
overflow tohidden
Explicitly set the body width to what it was in step 1.
var $body = $(document.body); var oldWidth = $body.innerWidth(); $body.css("overflow", "hidden"); $body.width(oldWidth);
Closing the modal:
- Set
body
overflow toauto
Set
body
width toauto
var $body = $(document.body); $body.css("overflow", "auto"); $body.width("auto");
Inspired by: http://jdsharp.us/jQuery/minute/calculate-scrollbar-width.php
Bootstrap's modal
automatically adds the class modal-open
to the body when a modal dialog is shown and removes it when the dialog is hidden. You can therefore add the following to your CSS:
body.modal-open {
overflow: hidden;
}
You could argue that the code above belongs to the Bootstrap CSS code base, but this is an easy fix to add it to your site.
Update 8th feb, 2013
This has now stopped working in Twitter Bootstrap v. 2.3.0 -- they no longer add the modal-open
class to the body.
A workaround would be to add the class to the body when the modal is about to be shown, and remove it when the modal is closed:
$("#myModal").on("show", function () {
$("body").addClass("modal-open");
}).on("hidden", function () {
$("body").removeClass("modal-open")
});
Update 11th march, 2013
Looks like the modal-open
class will return in Bootstrap 3.0, explicitly for the purpose of preventing the scroll:
Reintroduces .modal-open on the body (so we can nuke the scroll there)
See this: https://github.com/twitter/bootstrap/pull/6342 - look at the Modal section.
Simply hide the body overflow and it makes body not scrolling. When you hide the modal, revert it to automatic.
Here is the code:
$('#adminModal').modal().on('shown', function(){
$('body').css('overflow', 'hidden');
}).on('hidden', function(){
$('body').css('overflow', 'auto');
})