Prevent BODY from scrolling when a modal is opened
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.
How to prevent body scrolling while modal is open
The easiest way is change the body atributes.
When the modal is open, set the height to 100% and hidden the overflow. When the modal is closed change the atributes do initial values (auto).
You can made this using css class, so when modal is opened you set a class to body with this atributes then when the modal is closed you remove the class. Or you can made this using javascript, and set the style tributes of the body manually.
I made the last way for you.
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
document.body.style.overflow = "hidden"; // ADD THIS LINE
document.body.style.height = "100%"; // ADD THIS LINE
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
document.body.style.overflow = "auto"; // ADD THIS LINE
document.body.style.height = "auto"; // ADD THIS LINE
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
document.body.style.overflow = "auto"; // ADD THIS LINE
document.body.style.height = "auto"; // ADD THIS LINE
}
}
The lines with the "ADD THIS LINE" comment is the line you need to add in your code.
Of Course you can put the css styles in one class and add or remove the class with javascript or jquery.
How to disable body scrolling when modal is open IOS only
I've created the following solution, which works on iOS 12!
Although the embedded demo below uses Bootstrap 4, the same solution works equally well with Bootstrap 3 since none of the modal class or event names are different.
Step 1: Use fixed positioning to freeze the body
in place when the modal is open
When a Bootstrap modal is opened, a class called .modal-open
is added to the body
. Add the following additional styles to this class:
body {
&.modal-open {
bottom: 0;
left: 0;
position: fixed;
right: 0;
top: 0;
}
}
Now whenever a modal is opened, the body
will be fixed in place and sized to the same dimensions as the viewport itself. This completely prevents scrolling because there's nowhere and nothing to scroll to!
But: this also means that opening a modal will cause the page to jump to the top, because the body
no longer extends past the bottom edge of the viewport (assuming the page content is taller).
Step 2: Simulate the previous scroll distance while the modal is open
Bootstrap exposes events that fire when a modal is opened or closed. We can use these to solve the "jump to the top" issue by pulling the top of the body
up when a modal is opened, so that it looks like the scroll position hasn't changed:
$(function() {
var $window = $(window),
$body = $("body"),
$modal = $(".modal"),
scrollDistance = 0;
$modal.on("show.bs.modal", function() {
// Get the scroll distance at the time the modal was opened
scrollDistance = $window.scrollTop();
// Pull the top of the body up by that amount
$body.css("top", scrollDistance * -1);
});
});
However, the page will still jump to the top when the modal is closed because the scrollTop
value of the window
is still 0
.
Step 3: Reset everything when the modal is closed
Now we just need to hook into the event that fires when the modal is closed and put everything back how it was:
- Remove the fixed positioning and negative top value on the
body
- Set the window's scroll position back to what it was originally
$modal.on("hidden.bs.modal", function() {
// Remove the negative top value on the body
$body.css("top", "");
// Set the window's scroll position back to what it was before the modal was opened
$window.scrollTop(scrollDistance);
});
There's no need to manually remove the fixed positioning on the body
, because this is set through the .modal-open
class, which Bootstrap removes when the modal is closed.
Demo
Put it all together, and now you can prevent background scrolling on iOS while a modal is open without losing your scroll position!
Open the following link on an iOS device: https://daguy.github.io/ios-modal-fix/
stop scrolling on body when modal is open and allow scroll on modal divs
Using jQuery/JS to modify the body
's overflow
when the modal is opened, you can make it so the page will stop scrolling, and the modal will still be scrollable.
The key aspects of this solution are:
- The modal has
overflow: scroll;
set. - The body is set to
overflow: hidden;
when the modal is opened.
I mocked up a very simple example, see below:
$('.click').click(function(){ $('.modal').show(); $('body').css("overflow", "hidden");});
.content { height: 700px; width: 100%; background: grey;}
.click { background: blue; cursor: pointer;}
.modal { position: absolute; width: 100px; height: 100px; background: red; top: 50%; left: 50%; transform: translate(-50%, -50%); display: none; overflow: scroll;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><div class="content"> This is the main content that scrolls until the modal is opened. <div class="click">Click me to open modal</div> <div class="modal">This is a modal that requires me to scroll down on hence there is a lot of placeholder text in here that I am having to type man I should've used Lipsum.</div></div>
React: Prevent scroll when modal is open
Use state to track if the Modal is open and only hide scroll if it's true. Since you're using document.body.style.overflow = 'hidden'
in componentDidMount
, the component still gets mounted which calls the lifecycle method that hides the scroll on body.
export class Modal extends React.Component {
constructor(props) {
super(props);
this.state = {
open:false
}
}
componentDidMount() {
if(this.state.open){
document.body.style.overflow = 'hidden';
}
}
componentWillUnmount() {
document.body.style.overflow = 'unset';
}
render() {
return (
<React.Fragment>
{this.props.showAt ?
this.props.show ?
<div style={style} className={`${this.props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!this.props.showAt ? styles.modalWhiteFixed : ""}`}>
{this.props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
{this.props.children}
</div>
: null
:
this.props.show ?
<div className={`${this.props.className} ${styles.modal}`}>
<div style={style} className={`${this.props.sectionName} ${modalTypeStyle ? modalTypeStyle : styles.modalWhite} ${modalTypeSize ? modalTypeSize : styles.modalSmall} ${!this.props.showAt ? styles.modalWhiteFixed : ""}`}>
{this.props.arrowShape ? <div className={arrowTypeStyle ? arrowTypeStyle : styles.triangleToprightWhite} /> : null}
{this.props.children}
</div>
</div> :
null}
</React.Fragment>
)
}
}
Prevent background scrolling when overlay appears
One approach is hidden the overflow of the body element.
like this:
body.modal-open{
overflow:hidden;
}
so in this case when you popup the modal you add a class to body and then when you close it you remove that class.
another approach is using a javascript to disable the scroll like this:
document.documentElement.style.overflow = 'hidden';
document.body.scroll = "no";
and then return it with
document.documentElement.style.overflow = 'scroll';
document.body.scroll = "yes";
Related Topics
Replace Words in the Body Text
Reading Uploaded Text File Contents in Html
Text-Overflow Ellipsis on Left Side
How to Pass Parameter to Function Using in Addeventlistener
How to Get the Position of Text Within an Element
Add Svg Element to Existing Svg Using Dom
How to Force the Browser to Reload Cached CSS and JavaScript Files
How to Retrieve the Display Property of a Dom Element
Get the Device Width in JavaScript
Remove All Classes That Begin With a Certain String
How to Use Jquery and Jquery Plugins With Primefaces
Loading JavaScript into a Uiwebview from Resources
How to Get Query String Values in JavaScript
What Is the (Function() { } )() Construct in JavaScript
Difference Between Json and Object Literal Notation