iOS 10 Safari: Prevent scrolling behind a fixed overlay and maintain scroll position
please, add -webkit-overflow-scrolling: touch;
to the #overlay
element.
And add please this javascript code at the end of the body tag:
(function () {
var _overlay = document.getElementById('overlay');
var _clientY = null; // remember Y position on touch start
_overlay.addEventListener('touchstart', function (event) {
if (event.targetTouches.length === 1) {
// detect single touch
_clientY = event.targetTouches[0].clientY;
}
}, false);
_overlay.addEventListener('touchmove', function (event) {
if (event.targetTouches.length === 1) {
// detect single touch
disableRubberBand(event);
}
}, false);
function disableRubberBand(event) {
var clientY = event.targetTouches[0].clientY - _clientY;
if (_overlay.scrollTop === 0 && clientY > 0) {
// element is at the top of its scroll
event.preventDefault();
}
if (isOverlayTotallyScrolled() && clientY < 0) {
//element is at the top of its scroll
event.preventDefault();
}
}
function isOverlayTotallyScrolled() {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
return _overlay.scrollHeight - _overlay.scrollTop <= _overlay.clientHeight;
}
}())
I hope it helps you.
Combined Bohdan Didukh's approach with my previous approach to create an easy to use npm package to disable/enable body scroll.
https://github.com/willmcpo/body-scroll-lock
For more details on how the solution works, read https://medium.com/jsdownunder/locking-body-scroll-for-all-devices-22def9615177
I was trying to find a clean solution to this for a long time, and what seems to have worked best for me is setting pointer-events: none;
on the body, and then pointer-events: auto;
explicitly on the item I want to allow scrolling in.