Prevent overflow / rubberband scrolling on iOS
The solution:
Type 1:
The most basic solution to prevent overflow scrolling on the element itself is to prevent default on touch events.
document.body.addEventListener('touchmove', function(e) {
e.preventDefault();
});
This method however disables the browsers native momentum scroll and is thereby not suitable for most applications. With some refinement however (only prevent if at top scrolling up or at bottom scrolling down, ...) this method fixes most problems. Many possible implementations can be found in this SO post.
Type 2:
Overflow scrolling on the body however is not prevented by methods described above.
One possible solution which seems reasonable is to prevent the element from ever being at its top or bottom position as described as best solution on mentioned question.
anElement.addEventListener('touchstart', function( event ){
if( this.scrollTop === 0 ) {
this.scrollTop += 1;
} else if( this.scrollTop + this.offsetHeight >= this.scrollHeight ) {
this.scrollTop -= 1;
}
}
This however did not reliably work on iOS 9.3.2.
What did work however is setting position: fixed
on the <body>
element to prevent the body from moving. Please note however that this still does not completely stop type 2
from happening, which is why sometimes you cannot scroll/focus any element because in the background type2
with its focus lock is still happening (again, after you stop touching the screen for a moment it again works as expected).
While this is still far from being the optimal solution it seems to be the best we can get for the time speaking.
Edit: Please note that I am not sure if it is safe to put position: fixed
on a <body>
element. To track possible issues I have created following SO post. Apparently it might be better to create a wrapper element as child of body and set that element to position: fixed
to avoid zoom problemes.
Edit 2: The definite solution
The script iNoBounce works wonders. Just load it to the page and experience a bounce-free web application. So far I have not found any problems with this solution.
I see this issue is still relevant so...
Be aware of using position: fixed
on body. It may do weird scroll freeze bug - actually it will still "rubberband" but you will not see it.
see: Div scrolling freezes sometimes if I use -webkit-overflow-scrolling