IOS only / iPhone X / iPhone 7 etc.
Even jquery modal libraries don\'t work! https://jquerymodal.com/ - Open the modal on your iPhone and you will be able to scroll the
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:
body
$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/