jQuery UI accordion: enabling keyboard navigation

A couple of weeks back, Karl asked a question about jQuery UI’s Accordion interface widget and keyboard accessibility. I’ve got my head in various JavaScript frameworks at the moment, so I took a quick look.

This article is now a little out of date. The jQuery UI team seem to have updated the framework to use tabindex="-1", fixing one of the problems I outline below. The example code may now be obsolete. I hope to review this soon.

So, what’s an accordion when it’s at home?

You’ve got an accordion interface when you have a small collection of vertically-stacked, collapsible layers of content that a user can flip between. It’s a similar concept to tabbed interfaces where you view one chunk of content at a time, but in an accordion each of the interface controls are vertical and span the full width of the content. It’s easiest explained with an example (make sure you have JavaScript enabled).

Problems with keyboard accessibility

Karl was finding that, while you could navigate and control the accordion using the keyboard in Safari 3 and Internet Explorer 7, there were problems when using Firefox 3. I’m not yet sure why, but it didn’t work at all for me in Opera 9.6.

When testing with Firefox 3, I observed the following:

  • If there is a link inside the accordion control, you cannot navigate to it when tabbing forwards through the page. However, you can access the link when tabbing backwards using Shift+Tab.
  • You cannot tab back through the page from the accordion control using Shift+Tab. Keyboard navigation is trapped.

I traced the problem to the tabindex="0" that jQuery dynamically adds to the accordion controls. The idea is to actually improve accessibility; tabindex="0" should tell browsers to make the accordion control part of the tab order, no matter what type of element it is. For example, if you have a heading as a control for your accordion, setting tabindex="0" on it should allow you to tab to it, even though a heading is not normally accessible using a keyboard.

The onclick problem

Despite this seemingly life-saving technique for adding elements to the tab order of a page, it doesn’t necessarily ensure that our interface is now keyboard accessible. I’ll be doing some testing and explain in a follow-up entry. Following Alistair’s comment, I’ll clarify here by adding that the tabindex technique is valid, but I believe it needs to mature before it can be relied upon.

For now, I can only advise that developers use standard HTML control elements (such as <a> and <button>) to ensure accessibility to keyboard users.

Firefox has problems handling tabindex="0"

So, back to the problem at hand…

Unfortunately, it seems that Firefox has problems with tabindex="0", causing the keyboard navigation issue that Karl was experiencing. The technique could be a good solution, but only if it was widely supported by browsers and was sure to work with assistive technology.

It looks like Jörn Zaefferer is on the case at the jQuery end and is removing the tabindex attributes set by jQuery. In the meantime, this move will (hopefully) force developers to use standard HTML control elements for their interface controls. Unfortunately, the majority of developers may see their interfaces working when using a mouse, assume that it’s all okay, and not test keyboard accessibility.

Fixing it in the meantime

You can “undo” the tabindex that jQuery sets by setting up your accordion something like this:

	header: ".ui-accordion-header"
$('#accordion .ui-accordion-header').attr('tabindex','');

Here, we’ve told jQuery to blank all the tabindex attributes on the accordion “headers” (i.e. the accordion interface controls).

An even better solution would use standard HTML control elements (<a>, <button>, …) in the first place, as mentioned above. However, this can restrict your markup a little, and may not make much sense, for example, if you’ve marked up each of your accordion layers with a heading. In any case, you can always the accordion controls dynamically, giving you a bit more freedom as to what element you use.