5

I am currently working on a single page web app optimized for touch devices, mainly iOS. I've implemented the new iOS native scrolling via -webkit-overflow-scrolling: touch; and all works well except that we are still experiencing the apple elastic scroll effect on the whole page body.

This involves the whole page moving off the top/bottom of the viewport when a scroll ends or the body is pushed and really gives away the fact that this is a web app. I have followed various guidelines on how to prevent this and while they do work, they prevent inner scrollable elements from working altogether.

Here's a fiddle to demonstrate what I'm using so far.

Has anyone found a solution that disables body elastic scrolling but lets inner scrollables work?

madcapnmckay
  • 15,782
  • 6
  • 61
  • 78

3 Answers3

5

I've adapted the good solution from Conditionally block scrolling/touchmove event in mobile safari using Dojo:

var initialY = null;
dojo.connect(document, 'ontouchstart', function(e) {
    initialY = e.pageY;
});
dojo.connect(document, 'ontouchend', function(e) {
    initialY = null;
});
dojo.connect(document, 'ontouchcancel', function(e) {
    initialY = null;
});
dojo.connect(document, 'ontouchmove', function(e) {
    if(initialY !== null) {
        if(!dojo.query(e.target).closest('#content')[0]) {
            // The element to be scrolled is not the content node
            e.preventDefault();
            return;
        }

        var direction   = e.pageY - initialY;
        var contentNode = dojo.byId('content');

        if(direction > 0 && contentNode.scrollTop <= 0) {
            // The user is scrolling up, and the element is already scrolled to top
            e.preventDefault();
        } else if(direction < 0 && contentNode.scrollTop >= contentNode.scrollHeight - contentNode.clientHeight) {
            // The user is scrolling down, and the element is already scrolled to bottom
            e.preventDefault();
        }
    }
});

The element to be scrolled is #content in this case.

Community
  • 1
  • 1
Thomas Bachem
  • 1,545
  • 1
  • 16
  • 10
  • 1
    Are you sure this works? I couldn't replicate this working on fiddle...wondering if this is indeed a correct answer – zanona Apr 01 '12 at 21:51
  • Still works quite well for me. – Thomas Bachem Jun 22 '12 at 16:37
  • In IOS 7 this code will only prevent elastic scrolling once the page has been scrolled past its boundaries once. Eg: 1. you scroll down: it overscrolls 2. you scroll down again: no overscroll 3. you scroll up: it overscrolls 4. you scroll down: it overscrolls 5. you scroll down: no overscroll 6. you scroll down: no overscroll – Phedg1 Jun 16 '14 at 01:30
1

Maybe iScroll is what you're looking for (if I got your question right)

jln-dk
  • 294
  • 1
  • 2
  • 11
  • The problem with iscroll is that it isn't native and it only implements scrolling on a container as far as I am aware. The webkit overflow scrolling allows native touch scrolling on containers and works great. But the apple elastic body scrolling is still present no matter what scrolling solution you choose. – madcapnmckay Feb 02 '12 at 16:18
  • Actually, iScroll doesn't suffer from it, I think it puts a fix in place, it essentially disables all scrolling and then adds its handlers on top to enable it's scroll. I'm looking into doing similar myself but just letting native scroll continue. – madcapnmckay Feb 02 '12 at 19:36
0

At the risk of duplicating my post, I try to solve the same issue and so far am only this far:

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

This works if you have an overflow element that doesn't cover the whole screen, like in an iPad app for example. but it doesn't work if you have a mobile app and the entire viewport is covered by your overflowed element.

The only thing I could think of is to check the scrollTop() of the $('.scrollable') and then conditionally bind the preventDefault() if it's 0.

After trying, I noticed that the webkit UA reports scrollTop always as 0 when the element is scrolled to the top even when it does the "inside bounce" of the native overflow scroll. So i can't do anything since I'd require a negative scrollTop to set my condition.

Sigh. Frustrating.

tim
  • 3,823
  • 5
  • 34
  • 39