University of Missouri

Interface

Skip to search and archives

Illustration of a keyboard making a working connection to a dropdown menu

Building keyboard accessible dropdown menus

Published on by Joshua Hughes | Posts by This Author

When developing a dropdown menu for your site, it’s important not to assume that all your visitors will be navigating with a mouse. Some might be using the keyboard exclusively to navigate your website.

Fortunately, enabling keyboard access is a relatively simple task.

Here’s a typical dropdown menu example, one that follows the popular Suckerfish model:

It uses an unordered list, with second level lists for the dropdowns. These dropdowns are absolutely positioned off-screen until the user mouses over one of the top level menu items. The relevant CSS looks something like this:

.nav ul ul
{
    position: absolute;
    left: -9999em; /* push it off-screen */
}

.nav ul li:hover ul,
.nav ul li.hover ul
{
    left: 0; /* bring it back */
}

Note that the additional ul li.hover ul rule is specifically for Internet Explorer 6, which unfortunately doesn’t support the :hover pseudo class on anything besides the <a> tag. The hover class is applied with Javascript.

So take a second look at the demo again, and instead of using a mouse, try using the tab key to go through the links.

At most you’ll get an outline around any top level links that are selected, and no visual indication at all if one of the second level links are selected. So what do we do about this?

Javascript to the Rescue

First, we’re going to make the dropdown show up when a top level link or any of its children receive keyboard focus. We’re going to use jQuery, a popular Javascript framework, for this task:

$(document).ready(function()
{
    $(".nav").accessibleDropDown();
});

$.fn.accessibleDropDown = function ()
{
    var el = $(this);

    /* Setup dropdown menus for IE 6 */

    $("li", el).mouseover(function() {
        $(this).addClass("hover");
    }).mouseout(function() {
        $(this).removeClass("hover");
    });

    /* Make dropdown menus keyboard accessible */

    $("a", el).focus(function() {
        $(this).parents("li").addClass("hover");
    }).blur(function() {
        $(this).parents("li").removeClass("hover");
    });
}

Simply put, this script does two things: First, it adds the class hover to any <li> tags found within our menu (a <div> with a class of nav) on mouseover, removing it on mouseout. It does this primarily for the benefit of Internet Explorer 6, but this will be applied in all browsers with Javascript enabled.

Second, if any links within .nav receive keyboard focus, the class hover will be added to any <li> tags that are parents of the focused <a> tag. This allows the dropdown to be visible while the user is tabbing through the menu items.

Compliment :hover with :focus and :active

Now, making the dropdown visible on keyboard focus clears the primary accessibility hurdle, but it’s also good to have keyboard focus trigger the same visual effects you get when using the mouse.

To that end, almost anytime you’re using the :hover pseudo-class on an element that can takes keyboard focus (links, especially), you should have equivalent rules for the :focus and :active pseudo-classes.

Our CSS has two rules, one for top level links and one for second level links, that would benefit from this:

ul a:hover
{
    /* On hover, make top level links brown with white text */
}

and

ul li:hover ul a:hover,
ul li.hover ul a:hover
{
    /* On hover, give second level links a tan background */
}

 

To add the same effects for keyboard focus, these rules should look like this:

ul a:hover,
ul a:focus,
ul a:active
{
    /* On hover and focus, make top level links brown with white text */
}

and

.nav ul li:hover ul a:hover,
.nav ul li.hover ul a:hover,
.nav ul li.hover ul a:focus,
.nav ul li.hover ul a:active
{
    /* On hover and focus, give second level links a tan background */
}

 

Finally, it’s also a good idea to make one more change to the rule for top level links:

ul a:hover,
ul a:focus,
ul a:active,
.nav ul li.hover a
{
    ...
}

This allows the top level link to stay “selected” as you hover or tab across links in the dropdown menu.

So, let’s take a look at our revised demo:

You should be able to easily browse the menu simply using the tab key. Our menu is now beautiful and usable for all visitors.

7 Comments

  • Ben

    Thanks for posting. I have been looking for an accessibility solution for my suckerfish menu all morning long. Only after setting it up do I notice that your demo doesn’t work in Firefox (7) or Opera (11.5). I tab and tab away, and the anchors in the dropdown never appears. Looks great in Chrome, though! Is there something I’m missing?

  • Richard

    Hi Josh, nice example well explained. i have just noticed that dropdowns aren’t showing up on tabbing Chrome.

    • Josh Hughes

      Thanks Richard! I made a minor error with how the jQuery library was being loaded that was causing it not to work in Chrome. Should be fixed now.

      • Richard

        Hi Josh, That’s excellent thanks again for sharing this !

  • Rick

    If you have your mouse over a drop down, and start tabbing, it opens two sets of drop downs. Should it not focus on where the mouse is?

    • Josh Hughes

      I’ll give it some thought, but my initial reaction is that’s an edge case not worth supporting.

      It would probably take a fair bit of additional code to get those two navigation styles to work together in a sensical manner.

Comments are closed.