'IOS Safari: unwanted scroll when keyboard is opened and body scroll is disabled

There is a known technique to disable page scroll when modal window is opened.

CSS:

html {
  height: 100%;
}

body.disable-scroll {
  position: fixed;
  height: 100%;
  overflow: hidden;
}

HTML:

<!DOCTYPE html>
<html>

<head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
    <meta content="width=device-width, initial-scale=1.0, user-scalable=no" name="viewport">
</head>

<body class="disable-scroll">
    <div class="page-content">
        <input type="text">
        ... content ...
    </div>
</body>

</html>

But on IOS Safari scroll becomes enabled after virtual keyboard is opened. And it scrolls more than even window.innerHeight + window.scrollX. Some blank gap appears at bottom of the page. enter image description here

Editor's url
https://codesandbox.io/s/condescending-snow-skuo5?fontsize=14

Fullscreen url to check on IPhone
https://skuo5.codesandbox.io/
Just open on IPhone or in XCode with IOS 12+ try to scroll and then focus on Input and try to scroll again.



Solution 1:[1]

Just some info for anyone arriving here.

Safari thinks this is feature. There is a bug report here (let them know you don't like this "feature" =]).

When you open the keyboard, the browser's window is moved up and your content is hidden because the window is out of the screen. Other weird behaviors can happen too, like the one the OP showed.

Scrolling out of the screen

Check this blog post for more details and more examples of weird behaviors (I copied the image above from it): https://blog.opendigerati.com/the-eccentric-ways-of-ios-safari-with-the-keyboard-b5aa3f34228d

Solution 2:[2]

can you try this css please..

html {
  height: 100%;
}

body.disable-scroll {
  position: fixed;
  top:0;
  bottom:0;
  left:0;
  right:0;
  height: 100vh;
  overflow: hidden;
}

Solution 3:[3]

I did this in one of my projects...

When you open the keyboard use this on body

$(body).bind('touchmove', function (e) {
    e.preventDefault()
});

And then unbind it when you want to scroll again

$(body).unbind('touchmove');

If you combine it with height:100% or 100vh and overflow:hidden. It should work.

Solution 4:[4]

It is possible to listen to these viewport height changes in JS:

window.visualViewport.addEventListener(
  'resize', 
  event => console.log(event.target)
);

This works on iPhone (tested on physical iPhone 11 with iOS 15.1)

MDN doc: https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jpenna
Solution 2 sbrrk
Solution 3 Every Screamer
Solution 4 lipsumar