[Update 2010-09-17:] Check the new version.

Dion Almaer was faster than me blogging about TouchScroll. Here is what you are waiting for – the “official” blog post about TouchScroll and the link to the repository.

Here it is: TouchScroll, our scrolling layer for WebKit Mobile. It is JavaScript/CSS 3 based and allows for fixed elements like headers and toolbars on web pages when viewed on the iPhone or on Android. It works on the iPad, too. Check out the demo (short URL: http://u.nu/8uvg8) to see it in action – it works in Desktop Safari (at least kind of) or WebKit Nightly (very good), but I recommend you have a look at it on your iPhone, iPad, or Android based device.


While Safari Mobile features native scrolling, there are two reasons to re-implement scrolling with JavaScript: The original scrolling behavior is rather slow – we were looking for a solution that feels more fluid. And the viewport behavior of Mobile Safari and other mobile browsers using WebKit doesn’t allow for fixed positioned elements. It is optimized for document reading, not for building interfaces.

Our goal is to be able to deploy application interfaces to browsers of handheld devices that feel as familiar as possible for the user. TouchScroll enables developers to use fixed interface elements like headers and toolbars.

We also use PhoneGap a lot to deploy cross-platform applications onto smartphones, and we think that web based apps don’t need to feel like aliens for users. And we weren’t satisfied with existing solutions.


To add a scrolling capabilities to an element, that element must have a fixed size. Have a look at the demo for an elegant approach using

display: -webkit-box



<div class="scroller"><!-- some great contents --></div>


var scrollNode = document.querySelector(".scroller"), options = {};
var scroller = new TouchScroll(scrollNode, options);

At the moment, the only known option is elastic. Use

{elastic: true}

as second parameter to add the bouncing effect to the scroller.

Get it!

TouchScroll is available on github. Feel free to fork it and send patches back. You can also get a minimized file that includes the css-bezier library that TouchScroll depends on.

How is it done?

TouchScroll uses a combination of JavaScript and CSS 3. All animations are done with CSS transitions – no JavaScript intervals.

The elasticity effect when crossing the scroller bounds is achieved by dividing the bezier curve (used as timing function) into two sub-curves using my (yet to be finished) CSS Bezier library for JavaScript.


TouchScroll allows you to customize many aspects of the scrolling behaviour: Have a look at the


object at the top of the source file.

Customizable properties include bouncing behaviour and deceleration animation. Feel free to experiment. I know that scrolling is not as close to <insert device of choice> as possible. If you think you’ve found better values, just let me know.

Configurable properties include:

  • Scrolling threshold: The minimum pixel amount needed to begin scrolling
  • Flicking behavior: flicking threshold, friction, and deceleration animation.
  • The elasticity/bouncing effect: factor and maximum bounce length.
  • Snap back behavior: timing function and default duration.


After instanciation, each TouchScroll scroller re-adapts to its contents after




events on


as well as after


events on the scroller itself. That means, the scroller adapts to content additions and deletions.


TouchScroll is meant to be used with touch-based devices and also works well with a stylus (tested with a Wacom tablet). Don’t use it for desktop browsers and the like. Simply add

overflow: auto

to the scroller element for these cases. Zero-cost compatibility.

Hiding and Showing

If a scroller is instanciated with an layer that is not beeing displayed, it needs to be refreshed manually after making it visible. Simply use the




TouchScroll inserts two more


elements to the outer scroller container, that wrao the prior contents. That means, that the outer scroller element must not have padding. The CSS child selector (

a &gt; b

) won’t work any more after instancing TouchScroll on an element for the same reason.


Android has several problems that need to be solved. If you have solutions, please keep in mind that TouchScroll should remain compatible with WebKit as found on Android 1.5 and send us a patch.

  • When not preventing the default action of the initial touchstart event on Android, the following touchmove events queue up and fire just before the eventual touchend event. That makes scrolling impossible.Cancelling the touchstart event results in other problems: It prevents tapped elements from beeing focused or clicked. The current workaround – dispatching a synthesized click event – hides the focus rectangle and makes the focussing of form elements nearly impossible, which is even worse.That means: at the moment it is not possible to use TouchScroll in conjunction with forms on Android.I’d like to know whether there is a solution that eliminates the need to prevent the default action of touchstart.
  • Due to the lack of hardware acceleration, the rendering performance on Android isn’t nearly as good as on the Apple’s devices. We already invested a lot of work to achieve good performance. If you can do better, send us a patch!
  • Support for
    -webkit-transform: matrix(…)

    is broken in Android < v2.0. That affects reading the computed style of elements. We already worked around that issue using a regex-based parsing function for those devices.

Other Devices

The browser of S60 devices is based on WebKit, too. However, apart from the fact that TouchScroll does not work on those devices, you should simply set the overflow style of the scroll container to

overflow: auto

for these devices and benefit from native scrolling. The same goes for Nokia WRT apps.

I’ve done a quick test on the Palm Pre. Unfortunately, TouchScroll does not work in the browser of webOS. Moreover, I’m not sure whether it actually makes sense in this particular browser, as its overlays would lie directly on top of fixed elements at the bottom. In webOS apps you should probably use the native scroller anyway. Maybe I’ll do a short tutorial on how to instanciate TouchScroll on iPhone/Android and the webOS scroller when deploying a cross platform app to all of those devices.

What other devices are relevant? Let us know!

To Do

The official to-do-list:

  • Keep the scrollbars round while bouncing – I already know how to do this, so you can expect the solution in the next days.
  • Add an option to completely switch off scrollbars.
  • Find a solution to the event problems on Android – help greatly appreciated!