Clicking with a Keyboard

Not everyone can use a mouse.

Across the spectrum of disabilities, different types of users rely on different
mechanisms for navigating around a webpage. In many of these cases a pointing
device such as a mouse or trackpad is simply not an option, due to either
insufficient motor skills, or being unable to see.

In fact, a 2003 study of accessible technology potential
commissioned by Microsoft found that an estimated "7% (or 12 million) of
working-age adults have a severe dexterity difficulty or impairment," one that
would likely prevent them from using a mouse or trackpad.

It's tough to say how many are attempting use your website, of course, but
there is also the power user who prefers to stick to their keyboard while
using your website.

Not everyone wants to use a mouse. Still, the web is full of interactive elements which require a mouse. Why is that?

Let's talk about the most common offender - the <div>. Now, the <div>
itself is very useful, but it's vague. It's a broad container of sorts. Not a
button, not a navbar, not an image - just a big ol' rectangle taking up a few
rows in our webpage.

Yet, many try to make it one of those things and, rather unfortunately, miss
out on all the cool things that would happen if we had used the right tag
for the job.

Depicted below is a demo of the code above interacting with a mouse
pointer. The button works as expected.

Display

This example does pretty much exactly what you'd expect. We've got a "button"
and clicking it triggers some action - in this case, putting some text in a
separate <div> before it disappears.

Keyboard-accessible <div>s

But what if we want to add keyboard access to this "button"? First, we'll need
to understand that users access items with a keyboard through the tab order.
Links (<a>) and inputs (<input>) will, as you probably already know,
automatically be navigated to and from using the tab key.

Our fancy <div>, on the other hand, can't - a <div> (and many other tags
like <p>, <b>, etc) will not find themselves in the tab order, so we'll
have to put in some extra work. We'll start by specifying tabindex="0" on
the tag.

In the following example we've tabbed to the button and focused it (as shown
by the black outline), and now we'll attempt to activate the button using the
enter key (just as we would on a hyperlink or form).

<divid="action-button" tabindex="0">Display</div>

Depicted below is the same demo as before, this time interacting with
the enter key. The button does not seem to do anything.

enter

Display

Unfortunately, nothing happens :( Our "button" is listening for a click event,
but we're attempting to activate it with a keyboard.

Depicted below is a demo of the code above interacting with the enter key.
The button now works similarly to the mouse pointer example before.

enter

Display

I'll call that a success, sort of! The code's a bit longer now (even after
a bit of refactoring), but it definitely works - our "button" can be
activated with both a mouse and a keyboard, just like a real button.

But hold on a second, why don't we just use a real button?

Semantic buttons

As I briefly mentioned earlier, there's nothing special about a <div>. It
doesn't have any magical behavior, it's just a container. We can shape it,
paint it, and make it look like a button, but it's not a button.

We can write some extra JavaScript to make it act like a button, but it's
not a button.

In fact, we're doing all this extra work (and often skipping it), when in
reality we could just a real button, the semantic <button> tag. Let's try
it.

Depicted below is a demo of the code above interacting with both a mouse
pointer and the enter key. Both of these interactions work.

Display

enter

Display

Excellent! Now that we are using the semantic <button> tag, we get a click
event for free. No need to track both a click and keypress handler here,
just a click will do.

It turns out that in order to make our button accessible, we don't have to
do much. In fact, the only difference between our first example and this
one is that we've replaced the <div> with a <button> - seriously!

Sane markup goes a long way

Beyond the obvious markup clarity and keyboard accessibility gains, we also
unlock a few bonus features when we use a <button> instead of a <div>. For
instance, a copy of VoiceOver on OSX will display the following:

Letting users with screen readers know that "Display" corresponds to a button
that can be activated with either their enter key or space bar.

So go forth and prevent your contemporaries from skipping the semantic markup,
make sure your buttons play nicely with the keyboard, and stop trying to copy
browser behavior provided to you for free.