3

This question is more of an advice research, I do hope that it will be helpful for others and it won't closed, as I'm not quite sure where to ask for advice on this matter.

I've been developing for mobile for the past 6 months and I had the occasion to deal with all kinds of situations and bugs on various devices.

The most troubling was the scrolling issue, when it comes to scrolling in multiple areas of the website. On three projects that I have been working on I've been building a navigation that behaves the same way that the native iOS Facebook app has, or the Google website on mobile, etc. And for each one I came up with different solutions.

But a few days ago I have just released a new JavaScript library, drawerjs, that can be used to generate such navigation (so called off canvas concept). The difference between the other libs and this one is that is library agnostic, and it acts on touch behavior (the same way that the Facebook app behaves) not just open / close on click.

One of the things that I have left to implement is a solution for scrolling inside the menu and the navigation without affecting one another (most of the time when you scroll in such way, the content tends to scroll together with you menu or after you have reached the end of the menu scrolling).

I have two solutions in mind:

  • One approach would be to use the same principle I'm using for dragging the content and showing the navigation, on touchmove I prevent the default scrolling on document / content and I start translating the contents with the same amount you scroll. And with the same resistant behavior as a touch slider would have (when you exceed the boundaries and let go, the contents would translate back so it doesn't exceed the boundary anymore, or on swipe with the same behavior).

  • A second approach would be using the native overflow-scrolling that iOS has and would offer the same feel as described in the first approach. The downside of this would be that only iOS devices would have the nice resistant feature, but it would be, supposedly, less of a hassle the the first approach.

So I'm not quite sure which approach I should take, or if there any better solutions for that. I'm also trying to keep in mind that some users would like to hide the url bar, so scrolling on the body / html would have to be kept (on the y axis).

Roland
  • 9,321
  • 17
  • 79
  • 135
  • 2
    It is not recommended to hijack scrolling. This will disable hardware acceleration, and will slow down the device. – Vitim.us Aug 14 '13 at 17:04
  • Ok, so what you're saying is do not use the first option I had in mind, to write my own implementation that disables scrolling and adds a scrolling like functionality ? But how do I solve scrolling in multiple areas without scrolling the rest of the body when the scroll touches the end of the content in one area ? – Roland Aug 14 '13 at 20:12
  • have you tried 'position:fixed' – Vitim.us Aug 15 '13 at 00:32
  • On the body ? I have, but that fails in Android < 2.2 – Roland Aug 15 '13 at 06:25

2 Answers2

4

You could do touchmove . But as far as I understand, you want something like this? http://jsfiddle.net/2DwyH/

using

var menu = $('#menu')

menu.on('mousewheel', function(e, d) {
    if((this.scrollTop === (menu[0].scrollHeight - menu.height()) && d < 0) || (this.scrollTop === 0 && d > 0)) {
        e.preventDefault();
    }
});

Using this plugin from Brandon Aaron - github : https://github.com/brandonaaron/jquery-mousewheel

And it should work with Android: What DOM events are available to WebKit on Android?

Some more info here: Prevent scrolling of parent element?

Also without using the plugin above , using only jQuery you could do this like it says on the link above - answer from Troy Alford

$('.Scrollable').on('DOMMouseScroll mousewheel', function(ev) {
    var $this = $(this),
        scrollTop = this.scrollTop,
        scrollHeight = this.scrollHeight,
        height = $this.height(),
        delta = (ev.type == 'DOMMouseScroll' ?
            ev.originalEvent.detail * -40 :
            ev.originalEvent.wheelDelta),
        up = delta > 0;

    var prevent = function() {
        ev.stopPropagation();
        ev.preventDefault();
        ev.returnValue = false;
        return false;
    }

    if (!up && -delta > scrollHeight - height - scrollTop) {
        // Scrolling down, but this will take us past the bottom.
        $this.scrollTop(scrollHeight);
        return prevent();
    } else if (up && delta > scrollTop) {
        // Scrolling up, but this will take us past the top.
        $this.scrollTop(0);
        return prevent();
    }
});

The JS Fiddle he mentions: http://jsfiddle.net/TroyAlford/4wrxq/1/

Community
  • 1
  • 1
Vrashabh Irde
  • 14,129
  • 6
  • 51
  • 103
  • this sounds like a good idea, this way I can take advantage of the `overflow-scrolling` property which adds elastic scrolling on iOS. The only concern is that if I do prevent default, will it prevent default on the document or will it be on the body (but I can see that you're doing it on the menu) ? – Roland Aug 15 '13 at 07:34
  • Interesting. the jsfiddle seems to be working for me. which browser are you trying on. – Vrashabh Irde Aug 15 '13 at 08:11
  • That might be just it, I'll have to take a look into it, but it sounds better than what I had in mind. Just that I'll write my own implementation because I'm using vanilla js, no jquery or other library. And from the looks of it, the source code does not seem to be very complex – Roland Aug 15 '13 at 08:23
  • I've updated my answer to have a pure JQuery way of doing it, from another SO question which seems like something you could easily implement yourself considering you want to. Take a look at it – Vrashabh Irde Aug 15 '13 at 08:25
  • I only have one question, how will this play with the momentum scroll on iOS ? If it will prevent default it might break it – Roland Aug 15 '13 at 08:28
  • http://stackoverflow.com/questions/16889447/prevent-full-page-scrolling-ios , maybe this will give you some insight ? – Vrashabh Irde Aug 15 '13 at 08:31
  • This discussion has been very helpful :) – Roland Aug 15 '13 at 08:35
1

Why not just provide a fixed height to your widget (min and max will also do). Then define like these -

height: x px;
overflow-y: auto;

This way till the focus is inside the widget, it'll only overflow the widget, once outside the page will scroll without affecting widget content at all.

Bikas
  • 2,709
  • 14
  • 32
  • Will this work in Android v2.x - v3.0 ? Because those versions don't like the `auto` or `scroll` value of the `overflow` property. Since the height would be all I need, what if I use flexbox, then the height will already be drawn as if the content would have a height. And are you sure that after you end scrolling the content on one side it won't start scrolling on the other side if there is any content that can be scrolled there ? Because I did have that experience on iOS and Android – Roland Aug 08 '13 at 14:42
  • Android (< 4.0) ignores the overflow-* completely, and it scrolls anyway, but respects general overflow property to some extent. With my experience it only scrolls till the content and then had it over to parent content, i.e. if parent content is scrollable, there'll be scroll, else not. Just one more thing - Flexbox doesn't work well will older version of Android, can't tell for iOS though. – Bikas Aug 12 '13 at 06:16