JavaScript interaction must be input device independent

Time for a bit of what in my opinion is Accessibility 101: input device independency. For some reason it is common to see otherwise nice uses of JavaScript made inaccessible by developers forgetting that not everybody uses a mouse (or some other pointing device).

There are several groups of people who do not use a mouse or pointing device to interact with Web pages. A few examples:

As you can see there are reasons that affect people with disabilities, and others that affect everybody. So when developing a user interface you have to make sure that it does not depend on a particular input device. See also WCAG 1.0 Guideline 9. Design for device-independence.

The most common problems I see are drag-and-drop functionality and onclick event handlers added to arbitrary elements. For drag-and-drop, you need to give users an alternative way of interacting. How to do that is up to you and is not something I am going to go into here.

For onclick event handlers, the solution is simple. Always use an a element with a value assigned to its href attribute. In some cases a form control is a better choice, but I’ll use links here.

Doing so makes the functionality accessible to keyboard users and other people who do not use a mouse. And yes, you really need to consider those users. I was very surprised to see several people argue against supporting non-mouse users in Jonathan Snook’s SnookSurvey #2: To Link or Not?. I don’t buy any of their arguments, which mostly seem based on a misunderstanding of the problem.

I’ll illustrate the onclick case with a couple of code examples consisting of a list of terms and definitions, where the definitions are hidden until the user clicks on a term. The examples use inline event handlers, style attributes, and excessive class attributes for clarity – do not use this code.

The wrong way

Here is how to do this the inaccessible way:

<dl class="faq">
	<dt onclick="showDefinition('def1')">Term 1</dt>
		<dd class="def1" style="display:none">Definition 1</dd>
	<dt onclick="showDefinition('def2')">Term 2</dt>
		<dd class="def2" style="display:none">Definition 2a</dd>
		<dd class="def2" style="display:none">Definition 2b</dd>
</dl>

The dd elements are hidden when the page loads (if CSS is enabled). When the user clicks on a dt element, the showDefinition() function changes the display property for the corresponding dd elements, making them visible. You could also use CSS to change the cursor property when the user places the cursor on top of the dt elements as a way to indicate that they are clickable. I don’t personally like doing so since it is very confusing when JavaScript is unavailable – it looks like you can click the text since the cursor changes, but when you click nothing actually happens.

This works fine for people who use a mouse. But what if you don’t? When you tab through the page, focus is placed on links and form controls, allowing you to interact with them. But focus is not placed on other elements, even if they have an event handler assigned to them. Because of that, it is impossible for non-mouse users to interact with the page. Bad, bad, bad.

Note: Using CSS to hide an element and JavaScript to show it creates accessibility problems since people with CSS on and JavaScript off will not be able to display the hidden elements. The way around this problem is to use JavaScript to hide the elements as well. I am doing it the bad way here since it makes it easier to follow the examples.

The better way

The simple solution is to use links. All browsing devices can follow links, and if they support JavaScript, activating a link will trigger an onclick event. With that in mind, here is the markup that is keyboard friendly (again, inline stuff to show what I mean—imagine the links and event handlers having been inserted by a script):

<dl class="faq">
	<dt><a href="#" onclick="showDefinition('def1')">Term 1</a></dt>
		<dd class="def1" style="display:none">Definition 1</dd>
	<dt><a href="#" onclick="showDefinition('def2')">Term 2</a></dt>
		<dd class="def2" style="display:none">Definition 2a</dd>
		<dd class="def2" style="display:none">Definition 2b</dd>
</dl>

A JavaScript function runs when the page (or the DOM) is loaded, inserts the links, and cancels their default behaviour to prevent them from navigating to the URL in the href attribute. The links only trigger the showDefinition() function.

Note that neither of these examples are complete solutions. They are just meant to illustrate the different approaches. In a production situation the links would be added with unobtrusive JavaScript.

There are usability issues to keep in mind with any approach that deviates from the normal behaviour of web pages, but I’m not going into that here. The purpose of this article is to show that you must not make website interaction depend on a certain input device, and that there is an easy way to make sure everybody can use your interface.

For a more detailed and comprehensive discussion of this subject, I recommend Accessible JavaScript: Beyond the Mouse by James Edwards.

Update: I realise that I didn’t stress enough that my examples aren’t complete. The links in the second example would not be in the raw markup but inserted by a script, as I mention in the paragraph following the code listing.

Posted on August 21, 2007 in JavaScript, Accessibility