Optimizing “overflow:scroll” on iOS5 [UPDATE]


With the never webkit builds on iOS5 and Android ICS finally overflow:scroll works as expected. On iOS you also have the “native” scroll bounce, which is huge IMHO (with bounce I mean the ease when the scrolled viewport reaches the top/end). The app finally feels native, a big step for web apps.

It wasn’t the sluggishness and weak performance of iScroll and scrollability I was mad about, it was the wrong implementation of the bounce physics. I was always able the tell the difference of a native and a phonegap app by checking scroll views.

Get it working

Check example 1 (with iOS5+ device or simulator)

The magic happens with this line.

View code on gist.github.com

Without you would still have a touchmove scroll with one finger, however the “native” bounce comes with -webkit-overflow-scrolling:touch. I notices however one thing that differs from the native scroll. When the content to scroll is on top (e.g. you can’t scroll any further up) and try it anyways, the touchmove bubbles up. Try example 1 again (with iOS5+ device or simulator) In this case it bubble to the top window object which then will scroll the browser chrome. While this might be an expected behavior, it still feels not very native. Let’s fix this.

Make it even more native

Check example 2 (with iOS5+ device or simulator)

When you try the same here, you’ll notice that you can drag the scrolled content with the expected physics. This feels, well, simply amazing. I have been working with all the JavaScript scroll implementations for such a long time now and now it’s finally native. Yeah!

So how is it done?

View code on gist.github.com

Well, the magic is to include the scroll content into another container div, that has to have the same height as the parent scroll container and also the correct overflow settings set (-webkit-overflow-scrolling doesn’t seem to be needed). Note that the subcontainer has to have the exact same height, so no margin or padding or stuff allowed. Also note, that no JavaScript is required. This is pure css.

Here a video to illustrate the difference between example 1 and 2:

One last thing

Notice that in the previous example you can still scroll the browser chrome? Try it by dragging (touch moving) the grey background. If you have a web app (instead of a website) you might want to disable the scrolling of the window viewport entirely.

Check example 3 (with iOS5+ device or simulator)


View code on gist.github.com

Listen to the touchmove event on document level and prevent the default behavior. With this setting alone scrolling would be disabled globally, also in the overflow div. That why you need to set another touchmove listener to the scroll div and stop the bubbling. This event then will never reach the document object.

UPDATE – Arg, found an edge case

Or, actually not so edge. Check a variation of the previous example (with iOS5+ device or simulator) where there are not enough item for the div to be scrollable. When you try to scroll you’ll notice, that the browser chrome scrolls. Not good.

Here corrected example 4 (with iOS5+ device or simulator)

However, it adds more markup and more JavaScript. I would appreciate a smarter solution.