15

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/

juniortan
  • 196
  • 1
  • 1
  • 10
  • I tried using emulator on chrome and removed your styles from body.modal-open, and it worked without error. I cant scroll when modal is opened. This is what you want to achieve right? – Gokhan Demirhan Apr 22 '17 at 22:16
  • There is no error but the issue I am facing is when the modal is enabled swiping up/down will scroll the body instead of the modal. – juniortan Apr 22 '17 at 22:35
  • Yes, like I said when you remove the css for body.modal-open it is not scrolling the body on emulator on chrome. I didnt tested it with actual mobile device – Gokhan Demirhan Apr 22 '17 at 22:42
  • Yes, the issue affects iOS devices. – juniortan Apr 22 '17 at 23:10
  • @juniortan have you found a working solution? I am going through the same thing where the background scrolls but the modal itself does not, but only on iOS, and only sometimes. It appears more problematic around input boxes and the bottom of the modal. I feel like I've tried everything under the sun – Jgoo83 Jun 20 '17 at 19:35
  • Possible duplicate of [How to prevent background scrolling when Bootstrap 3 modal open on mobile browsers?](https://stackoverflow.com/questions/19060301/how-to-prevent-background-scrolling-when-bootstrap-3-modal-open-on-mobile-browse) – Mugur 'Bud' Chirica Aug 14 '17 at 14:20

6 Answers6

26

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).

Rarblack
  • 4,559
  • 4
  • 22
  • 33
Klaas van der Weij
  • 1,065
  • 10
  • 13
  • 1
    This is the only thing that has properly clobbered scrolling on iOS for me after an hour of trying. Thanks! – Zack Oct 25 '18 at 16:12
  • Why isn't this the solution? This is the only thing that actually works after days of me searching through a bunch of really bad solutions. Thanks man! – Jabberwocky Nov 19 '18 at 12:34
  • 1
    I tried using a third-party plugin "body-scroll-lock" that claimed to work with iOS, but ultimately didn't. I'm seeing THIS to be a better solution, and the only thing to work on Apple Devices – Murphy1976 Jan 14 '19 at 14:54
  • This breaks tooltips in modals, because the `translate3d` or `top` property of the tooltip doesn't take into account the negative top margin of the `html` element. If you scroll down the page before opening the modal, the tooltip will be positioned higher than it should be. – crenshaw-dev Apr 16 '19 at 15:37
  • You can get around that by setting the `container` option of the `$().tooltip()` function to be the modal element. – crenshaw-dev Apr 16 '19 at 15:56
  • I started this question 2 years ago. Seems like there is a better answer now. Marked as answer. – juniortan Dec 11 '19 at 04:32
  • Finally a decent solution! – Duong Nguyen Dec 03 '20 at 04:04
10

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;
}
1

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);
JIm
  • 87
  • 1
  • 3
0

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');
kofifus
  • 17,260
  • 17
  • 99
  • 173
0

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);
};
Kuldeep Bhimte
  • 961
  • 1
  • 10
  • 25
0

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);
        });
    }
trop yes
  • 47
  • 1
  • 6