Reputation: 206
So there is this known issue with modal on iOS, when the modal is enabled swiping up/down will scroll the body instead of the modal.
Using bootstrap 3.3.7
Tried to google it, most suggested adding
body.modal-open {
overflow: hidden !important;
}
but it doesn't work.
Some suggested,
body.modal-open {
position: fixed;
}
But background will jump to the top of the page.
So for now I am using,
body.modal-open {
overflow: hidden !important;
position: fixed;
width: 100%;
}
#exampleModal {
background: black;
}
As a work-around so the jump can't be seen(but still noticeable)
Is there other solutions to this?
This is the site i am working on http://www.einproductions.com/
Upvotes: 15
Views: 21060
Reputation: 57
This will prevent page scrolling while Modal is opened on iOS mobile
if ($(window).width() < 960) {
let previousScrollY = 0;
$(document).on('show.bs.modal', () => {
previousScrollY = window.scrollY;
$('html').addClass('modal-open').css({
marginTop: -previousScrollY,
overflow: 'hidden',
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'fixed',
});
}).on('hidden.bs.modal', () => {
$('html').removeClass('modal-open').css({
marginTop: 0,
overflow: 'visible',
left: 'auto',
right: 'auto',
top: 'auto',
bottom: 'auto',
position: 'static',
});
window.scrollTo(0, previousScrollY);
});
}
Upvotes: 0
Reputation: 959
Import this file and use the enableBodyScroll
and disableBodyScroll
functions to lock and unlock the body scroll.
using css
top
property will exactly navigate back to the previous position. It eliminate the drawback of dealing with the floating point margin.
const toggleBodyScroll = (position, initialMargin) => {
document.body.style.position = position;
document.body.style.top = initialMargin;
};
const getScrolledPosition = () => {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
};
const scrollToPrevPosition = (scrolledPosition) => {
window.scrollTo(0, scrolledPosition);
};
const getWindowTop = () => {
return window.getComputedStyle(document.body).getPropertyValue('top');
};
export const disableBodyScroll = () => {
toggleBodyScroll('fixed', `-${getScrolledPosition()}px`);
};
export const enableBodyScroll = () => {
const scrollPosition = 0 - parseInt(getWindowTop());
toggleBodyScroll('static', 0);
scrollToPrevPosition(scrollPosition);
};
Upvotes: 0
Reputation: 19305
None of the above answers worked for me, the modal kept disappearing and I ended up with a brute force approach which is ugly and inefficient but works !
$('body').on('touchstart touchmove touchend', e => {
let scrollDisabled=$('.scroll-disable');
if (scrollDisabled.length > 0 && scrollDisabled.has($(e.target)).length===0) {
e.preventDefault();
e.stopPropagation();
}
});
setInterval(() => $('.modal:visible').css('top', '20px'), 100);
$(document).on({
'show.bs.modal': e => $(e.target).addClass('scroll-disable'),
'hidden.bs.modal': e => $(e.target).removeClass('scroll-disable')
}, '.modal');
Upvotes: 0
Reputation: 1114
I've taken the solutions of @Aditya Prasanthi and @JIm, since one fixes the background-scrolling and the other fixes the skip-to-the-top after closing the modal, and turned them into one bare-minimum JS script:
let previousScrollY = 0;
$(document).on('show.bs.modal', () => {
previousScrollY = window.scrollY;
$('html').addClass('modal-open').css({
marginTop: -previousScrollY,
overflow: 'hidden',
left: 0,
right: 0,
top: 0,
bottom: 0,
position: 'fixed',
});
}).on('hidden.bs.modal', () => {
$('html').removeClass('modal-open').css({
marginTop: 0,
overflow: 'visible',
left: 'auto',
right: 'auto',
top: 'auto',
bottom: 'auto',
position: 'static',
});
window.scrollTo(0, previousScrollY);
});
It's, of course, possible and even adviced to use a class to set and unset the CSS for the body, however, I choose this solution to resolve a problem just in one place (and not require external CSS as well).
Upvotes: 26
Reputation: 97
My solution:
scrollPos = window.scrollY - get current scroll position.
body { position: fixed;
margin-top: -**scrollPos** px);
}
Then modal is closed:
body {position: "";
margin-top: "";
}
and return scroll position to point before opened modal window:
window.scrollTo(0, scrollPos);
Upvotes: 1
Reputation: 109
refer to Does overflow:hidden applied to <body> work on iPhone Safari?
Added .freezePage to html and body when modal is showing
$('.modal').on('shown.bs.modal', function (e) {
$('html').addClass('freezePage');
$('body').addClass('freezePage');
});
$('.modal').on('hidden.bs.modal', function (e) {
$('html').removeClass('freezePage');
$('body').removeClass('freezePage');
});
the CSS
.freezePage{
overflow: hidden;
height: 100%;
position: relative;
}
Upvotes: 10