Back to blog

Native overflow scrolling with momentum in iOS 5+

May 10, 2014 - Posted in CSS Posted by:

Since the flood of touch devices into the market following the launch of the iPhone, users have had to learn and get used to a whole new set of interactions. These feel natural – simple things like swipe and pinch zoom are a given across every device and everyone from ages 1-101 can swipe. But there are also more custom/device specific interactions that have become ubiquitous. For example “pull down to refresh”, “five finger pinch” to get back to the homescreen on iPads or “four finger swipe” to move between open apps, an ‘alt + tab’ equivalent.

These are all native so are hardware accelerated, smooth and consistent. Some of these and other native interactions have made their way into web use. The trouble with this though is that because they are device specific, there usually isn’t an easy way to replicate these on the web. So we have to rely on libraries like hook.js for pull to refresh. From my experience these work OK but aren’t quite as smooth as their native counterparts but to me, there’s an even bigger problem:

These interactions were designed with touch in mind and seeing these make their way back to full desktop experiences with traditional inputs is painful – just try the hookjs demo with a mouse and you’ll see what I mean.

Thankfully though, there is one feature that’s made its way into mobile webkit that is actually native and that’s momentum scrolling which is pretty easy to implement. Use the following on whatever you want to be your scroll container:

overflow: scroll;
-webkit-overflow-scrolling: touch;

Devices that support it will have lovely, native scrolling with momentum and devices that don’t will just continue scrolling as normal – with a 1:! movement with you finger.

There’s an issue when using child elements of the scroller being positioned relative or absolute, but there’s a quick hack that seems to work nicely which is to apply an empty 3d transform to the children of the scroller, transform: translate3d(0, 0, 0).