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.
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.
Just went through tedious searching and seems that's an issue with iPhone as you have pointed in following article : https://blog.opendigerati.com/the-eccentric-ways-of-ios-safari-with-the-keyboard-b5aa3f34228d
So there is no way you can do it with css for sure.
But that doesn't stops you from using JQuery and Javascript >:)
Here is an untidy work around for your scenario. Have tested with multiple text boxes too on iPhone only:
document.getElementById("app").innerHTML = `
<div class="page-content">
<input type="text"
onfocus="disableScrolling(this)"
onfocusout="enableScrolling(this)">
<p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p>
<input type="text"
id="text2"
onfocus="disableScrolling(this)"
onfocusout="enableScrolling(this)">
<p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p><p>Page content</p>
</div>`;
var currentElem;
function stopScroll()
{
if(currentElem)
{
var top = $("input:focus").offset().top;
$('html, body').stop().animate({
scrollTop: top
}, 500, function(){});
}
}
function disableScrolling(elem)
{
currentElem = elem;
document.addEventListener("touchend", stopScroll);
setTimeout(function()
{
stopScroll();
},10);
}
function enableScrolling()
{
currentElem = undefined;
document.removeEventListener("touchend", stopScroll);
}
html {
height: 100%;
scroll-behavior: smooth;
}
body.disable-scroll {
position: fixed;
height: 100%;
overflow: hidden;
}
.page-content {
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body class="disable-scroll">
<div id="app"></div>
<div>End of body</div>
</body>
Problem : User can scroll away while focusing on
textbox
Assuming that,
Solution : Allow user to scroll where ever he want and once he is done bring him back smoothly to where you want him to be;
input:focused
:p
Note : I have used JQuery to make things simpler. If you want to use pure javascript, you can find the replacement for the specific codes.