Journal tags: delay

3

Without delay

When I wrote about mobile Safari adding support for touch-action: manipulation, I finished with this snarky observation:

Anyway, I’m off to update my CSS even though this latest fix probably won’t land in mobile Safari until, oh ….probably next October.

Historically, Apple have tied mobile Safari updates to iOS version number increments, and they happen about once a year. But this time, it looks like my snark was unfounded:

On Safari for iOS, the 350 ms wait time to detect a second tap has been removed to create a “fast-tap” response. This is enabled for pages that declare a viewport with either width=device-width or user-scalable=no. Authors can also opt in to fast-tap behavior on specific elements by using the CSS touch-action property, using the manipulation value.

That’s from the release notes for Safari 9.1—a point release.

I’m very pleased to have been absolutely wrong with my prediction of Apple’s timing.

Delay

Mobile browser vendors have faced a dilemma for quite a while. They’ve got this double-tap gesture that allows users to zoom in on part of a page (particularly handy on non-responsive sites). But that means that every time a user makes a single tap, the browser has to wait for just a moment to see if it’s followed by another tap. “Just a moment” in this case works out to be somewhere between 300 and 350 milliseconds. So every time a user is trying to click a link or press a button on a web page, there’s a slight but noticeable delay.

For a while, mobile browsers tried to “solve” the problem by removing the delay if the viewport size had been set to non-scalable using a meta viewport declaration of user-scalable="no". In other words, the browser was rewarding bad behaviour: sites that deliberately broke accessibility by removing the ability to zoom were the ones that felt snappier than their accessible counterparts.

Fortunately Android changed their default behaviour. They decided to remove the tap delay for any site that had a meta viewport declaration of width=device-width (which is pretty much every responsive website). That still left Apple.

I discussed this a couple of years ago with Tess (my go-to person on the inside of the infinite loop):

She’d prefer a per-element solution rather than a per-document meta element. An attribute? Or maybe a CSS declaration similar to pointer events?

I thought for a minute, and then I spitballed this idea: what if the 300 millisecond delay only applied to non-focusable elements?

After all, the tap delay is only noticeable when you’re trying to tap on a focusable element: links, buttons, form fields. Double tapping tends to happen on text content: divs, paragraphs, sections.

Well, the Webkit team have announced their solution. As well as following Android’s lead and removing the delay for responsive sites, they’ve also provided a way for authors to declare which elements should have the delay removed using the CSS property touch-action:

Putting touch-action: manipulation; on a clickable element makes WebKit consider touches that begin on the element only for the purposes of panning and pinching to zoom. This means WebKit does not consider double-tap gestures on the element, so single taps are dispatched immediately.

So to get the behaviour I was hoping for—no delay on focusable elements—I can add this line to my CSS:

a, button, input, select, textarea, label, summary {
  touch-action: manipulation;
}

That ought to do it. I suppose I could also throw [tabindex]:not([tabindex="-1"]) into that list of selectors.

It probably goes without saying, but you shouldn’t do:

* { touch-action: manipulation; }

or:

body { touch-action: manipulation; }

That default behaviour of touch-action: auto is still what you want on most elements.

Anyway, I’m off to update my CSS even though this latest fix probably won’t land in mobile Safari until, oh ….probably next October.

Double tap delay

Even though my encounter with Tess yesterday was brief, we still managed to turn the conversation to browsers, standards, and all things web in our brief chat.

Specifically, we talked about this proposal in Blink related to the 300 millisecond delay that mobile browsers introduce after a tap event.

Why do browsers have this 300 millisecond delay? Well, you know when you’re looking at fixed-width desktop-based website on a mobile phone, and everything is zoomed out, and one of the ways that you can zoom in to a specific portion of the page is to double tap on that content? A double tap is defined as two taps less than 300 milliseconds apart. So whenever you tap on something in a touch-based browser, it needs to wait for that length of time to see if you’re going to turn that single tap into a double tap.

The overall effect is that tap actions feel a little bit laggy on the web compared to native apps. You can fix this by using the fastclick code from FT Labs, but I always feel weird solving a problem on mobile by throwing more front-end code at it.

Hence the Blink proposal: if the author has used a meta viewport declaration to set width=device-width (effectively saying “hey, I know what I’m doing: this content doesn’t need to be zoomed”), then the 300 millisecond delay could be removed from tap events. Note: this only affects double taps—pinch zoom is unaffected.

This sounds like a sensible idea to me, but Tess says that she sometimes still likes to double tap to zoom even in responsive designs. She’d prefer a per-element solution rather than a per-document meta element. An attribute? Or maybe a CSS declaration similar to pointer events?

I thought for a minute, and then I spitballed this idea: what if the 300 millisecond delay only applied to non-focusable elements?

After all, the tap delay is only noticeable when you’re trying to tap on a focusable element: links, buttons, form fields. Double tapping tends to happen on text content: divs, paragraphs, sections. That’s assuming you are actually using buttons and links for buttons and links—not spans or divs a-la Google.

And if the author decides they want to remove the tap delay on a non-focusable element, they can always make it focusable by adding tabindex=-1 (if that still works …does that still work? I don’t even know any more).

Anyway, that was my not-very-considered idea, but on first pass, it doesn’t strike me as being obviously stupid or crazy.

So, how about it, browser makers? Does removing the 300 millisecond delay on focusable elements—possibly in combination with the meta viewport declaration—make sense?