How to prevent document scrolling but allow scrolling inside div elements on websites for iOS and Android?

How about this CSS only solution:

https://jsfiddle.net/Volker_E/jwGBy/24/

body gets position: fixed; and every other element you wish an overflow: scroll;. Works on mobile Chrome (WebKit)/Firefox 19/Opera 12.

You'll also see my various attempts towards a jQuery solution. But as soon as you're binding touchmove/touchstart to document, it hinders scrolling in the child div no matter if unbinded or not.

Disclaimer: Solutions to this problem are in many ways basically not very nice UX-wise! You'll never know how big the viewport of your visitors exactly is or which font-size they are using (client user-agent style like), therefore it could easily be, that important content is hidden to them in your document.


Finally, I got it to work. Really simple:

var $layer = $("#layer");
$layer.bind('touchstart', function (ev) {
    var $this = $(this);
    var layer = $layer.get(0);

    if ($this.scrollTop() === 0) $this.scrollTop(1);
    var scrollTop = layer.scrollTop;
    var scrollHeight = layer.scrollHeight;
    var offsetHeight = layer.offsetHeight;
    var contentHeight = scrollHeight - offsetHeight;
    if (contentHeight == scrollTop) $this.scrollTop(scrollTop-1);
});

Maybe I misunderstood the question, but if I'm correct:

You want not to be able to scroll except a certain element so you:

$(document).bind("touchmove", function(e){
    e.preventDefault();
});

Prevent everything within the document.


Why don't you just stop the event bubbling on the element where you wish to scroll? (PS: you don't have to prevent touchstart -> if you use touch start for selecting elements instead of clicks that is prevented as well, touch move is only needed because then it is actually tracing the movement)

$('#element').on('touchmove', function (e) {
     e.stopPropagation();
});

Now on the element CSS

#element {
   overflow-y: scroll; // (vertical) 
   overflow-x: hidden; // (horizontal)
}

If you are on a mobile device, you can even go a step further. You can force hardware accelerated scrolling (though not all mobile browsers support this);

Browser Overflow scroll:

Android Browser Yes
Blackberry Browser  Yes
Chrome for Mobile   Yes
Firefox Mobile  Yes
IE Mobile           Yes
Opera Mini          No
Opera Mobile    Kinda
Safari          Yes

#element.nativescroll {
    -webkit-overflow-scrolling: touch;
}

normal:

<div id="element"></div>

native feel:

<div id="element" class="nativescroll"></div>