iOS Safari/Chrome - Unwanted scrolling when focusing an input inside the modal

Limon Monte picture Limon Monte · May 18, 2016 · Viewed 26.9k times · Source

Tested in Safari and Chrome - the same result, so I think it's iOS issue.

This happens only if there's an input inside the modal and I tap that input. In the same moment that input got focus and native iOS keyboard become visible.

Page below modal in the same moment is automatically scrolled to 50% of its height. This behaviour is totally unwanted and I have no clue how to prevent this default iOS "feature".

Demo:

enter image description here

Answer

Jack picture Jack · Oct 14, 2016

Just adding an answer here in case people stumble upon this question (rather than your other question, which has a great demo to illustrate this issue)

We are facing a similar issue at work. As you mentioned, the offset is always ~50% of the height of the page, which happens regardless of where your initial offset is.

In the past, when I observed a similar "jumping" with earlier iOS versions (albeit, much less dramatic jumping), I have usually worked around this by applying position: fixed (or relative) to the body (which allows overflow: hidden to properly work).

However, this has the unattended consequence of jumping the user back to the top of the page, if they've scrolled down.

So, if you're open to addressing this issue with some JavaScript, here's a fix/hack I've thrown together:

// Tapping into swal events
onOpen: function () {
  var offset = document.body.scrollTop;
  document.body.style.top = (offset * -1) + 'px';
  document.body.classList.add('modal--opened');
},
onClose: function () {
  var offset = parseInt(document.body.style.top, 10);
  document.body.classList.remove('modal--opened');
  document.body.scrollTop = (offset * -1);
}

And what the CSS looks like:

.modal--opened {
  position: fixed;
  left: 0;
  right: 0;
}

Here's a fork of your demo page (from your other question), to illustrate: https://jpattishall.github.io/sweetalert2/ios-bug.html

And for those who are looking for a more general fix, you could do something like the following when opening/closing a modal:

function toggleModal() {
    var offset;
    if (document.body.classList.contains('modal--opened')) {
        offset = parseInt(document.body.style.top, 10);
        document.body.classList.remove('modal--opened');
        document.body.scrollTop = (offset * -1);
    } else {
        offset = document.body.scrollTop;
        document.body.style.top = (offset * -1) + 'px';
        document.body.classList.add('modal--opened');
    }
}

Edit: To avoid the "shifting/unshifting" on desktops, I would suggest feature detection/ua sniffing to apply this to only mobile safari.