Mouse & Touch Events Done Right

– 02/23/13

This article is old. Some functionality may be broken or downright missing.

Lately I’ve noticed that we as front-end developers have grown impatient as we wait for web technologies to “catch up” with their native counterparts. It’s those black eyes of web technologies that separate native from the web: those little screen flickers, those buttons that don’t render pixel perfect, those touch events that don’t seem to trigger at the right time, or those less-than-fluid animations that ruin every argument we’ve ever made for the web.

So, like good engineers, we’ve found ways to fix ( see shim ) some of the web’s weaknesses. One of the main places we’ve tried to “shim” the web to be more like native is in the mobile browser. We’ve forgotten at times that many of the best engines that power the web (Webkit, Gecko, Presto [RIP]) were built by some of the most brilliant engineers on the planet.

Let’s look at some of the ways in which we’ve attempted to shim the mobile web to be more like native.

The 300ms Touch Delay

The folks over at Google have written an article, Creating Fast Buttons for Mobile Web Applications, which chronicles some of the “limitations” of user interfaces on the mobile web, and steps one can take to fix them.

One technique the article suggests is to implement fast buttons, which create the illusions of snappy, native-like UI elements. This is done by binding to touchstart or click events based on device type.

The article points out the 300ms delay that mobile browsers introduce and why:

The reason for this is that the browser is waiting to see if you are actually performing a double tap.

The article does not mention, however, two other main design decisions which are affected by the 300ms delay:

  1. Scrolling a list of buttons

  2. Cancel-able button interactions

Scrolling a list of Fast Buttons

Take for instance the following UI with the fast button implementation. In the list below, if the device is touch-enabled, we’ll bind to touchstart, otherwise we’ll bind to click events.

Try scrolling the following list without actually activating a button on a touch device.

…that’s right, buttons activated all willy-nilly. No good. Fast buttons, for this example, are dumb buttons.

Scrolling a list of Normal (non-fast) Buttons

Now take for instance the following UI without the fast button implementation. That is, all buttons in this list are activated on click, regardless of whether or not the device supports touch events.

Again, try scrolling the following list without activating a button on a touch device.

… that’s right. Note that you cannot accidentally activate a button. However, in this implementation, a button can only be activated after the 300ms delay.

The Cancel-able Button

Most touch devices implement a concept of cancel-able touch interactions. When an interaction is initiated via touch, the interaction can be cancelled by holding then sliding away from the target. On a touch device, touch and hold each button. Notice that the “fast button” is immediately activated.

The non-fast button is not activated while you touch and hold, and dragging your finger away cancels the interaction.

I am a “fast button”. I am not cancelable on a touch device.

I am not a “fast button”. I am cancelable on a touch device.

The blue button above is activated on touchstart for devices with touch events – the very instant the button is touched, it is activated. No delay at all.

The yellow button above is activated on click only, regardless of the device. Although a small delay exists when touched, the interaction is cancel-able, which can be imperative to various UIs.

Conclusions regarding the Fast Button implementation

Remember: mobile browsers were designed the way they were designed for a reason. Lots of thought and energy went into every interaction and paradigm. Therefore, developers should take great care when overriding browser defaults.

In the case of the scrolling buttons lists, take care to allow your users to scroll without firing events they don’t intend to fire.

Furthermore, for buttons in your user interface that have more serious implications (e.g. buttons that delete something, buttons that send a irretractable message), don’t apply the fast button technique. By not applying the fast button technique, you’re allowing your users the option of bailing out of an action at the last moment.

My main tip: use your best judgement. Take special care to let the user do what they want to do, and don’t force your users into interactions they don’t expect on the platform they’re currently using.

A tip for handling touch events in Javascript

First off, make sure you understand and use Modernizr and look at Modernizr’s touch test suite. I found that one of the best ways to handle touch/click events gracefully is, with the help of Modernizr, like so:

var events        = {}
events.startEvent = Modernizr.touch ? 'touchstart' : 'click';
events.endEvent   = Modernizr.touch ? 'touchend' : 'mouseup';
events.moveEvents = Modernizr.touch ? 'touchmove' : 'mousemove';

… then, you can bind to a DOM element like so:

jQuery('.button').on( events.startEvent, function(){
  // I fire on 'touchstart' on touch devices
  // but on 'click' on non-touch devices