I created a website with jQueryMobile for iOS and Android.
I don't want the document itself to scroll. Instead, just an area (a <div>
element) should be scrollable (via css property overflow-y:scroll
).
So I disabled document scrolling via:
$(document).bind("touchstart", function(e){
e.preventDefault();
});
$(document).bind("touchmove", function(e){
e.preventDefault();
});
But that will also disable scrolling for all other elements in the document, no matter if overflow:scroll
is set or not.
How can I solve this?
First position the innerScroller wherever you want on the screen and then fix outerScroller by setting it css to 'hidden'. When you want to restore it you can set it back to 'auto' or 'scroll', whichever you used previously.
In my case, I have a scrollable body and a scrollable floating menu over it. Both have to be scrollable, but I had to prevent body scrolling when "floating menu" (position:fixed) received touch events and was scrolling and it reached top or bottom. By default browser then started to scroll the body.
I really liked jimmont's answer, but unfortunatelly it did not work well on all devices and browsers, especially with a fast and long swipe.
I ended up using MOMENTUM SCROLLING USING JQUERY (hnldesign.nl) on floating menu, which prevents default browser scrolling and then animates scrolling itself. I include that code here for completeness:
Another observation: I also tried various combinations of e.stopPropagation() on menu div and e.preventDefault() on window/body at touchmove event, but without success, I only managed to prevent scrolling I wanted and not scrolling I did not want. I also tried to have a div over whole document, with z-index between document and menu, visible only between touchstart and touchend, but it did not receive touchmove event (because it was under menu div).
Finally, I got it to work. Really simple:
This is what worked for me for Android and IOS devices.
Imagine that we have a
div class="backdrop">
element that we don't want to be scrolled, ever. But we want to be able to scroll over an element that is on top of thisbackdrop
.So, we listen to the
touchmove
event, if we're scrolling over the backdrop, we prevent it. If we're scrolling over something else, we allow it but stop its propagation so it doesn't scroll also thebackdrop
.Of course this is pretty basic and can be re-worked and expanded a lot, but this is what fixed my issue in a VueJs2 project.
Hope it helps! ;)
How about this CSS only solution:
https://jsfiddle.net/Volker_E/jwGBy/24/
body
getsposition: fixed;
and every other element you wish anoverflow: 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.
I was looking for a solution that did not require calling out specific areas that should scroll. Piecing together a few resources, here is what worked for me:
This code requires jQuery.
Sources:
Update
I needed a vanilla JavaScript version of this, so the following is a modified version. I implemented a margin-checker and something that explicitly allows input/textareas to be clickable (I was running into issues with this on the project I used it on...it may not be necessary for your project). Keep in mind this is ES6 code.