Posted By

chrisdpratt on 02/10/10


Tagged

dropdown navigation jquery accessibility focus


Versions (?)

Accessible Dropdown Navigation (Handling Focus with jQuery)


 / Published in: JavaScript
 

Dropdown navigation is fairly inaccessible as it depends on hover events in 99.9% of cases. Tabbing through the navigation with the keyboard fails to reveal the dropdowns leaving those navigation items virtually inaccessible. Worse, each of the hidden anchors still take focus on tab, so the user is left blind until they've tabbed enough to get to the next top-level navigation item.

The code below selects all the anchor elements in dropdown menus and adds focus and blur events to them. The focus event adds a class of dropdown-visible to the top-level list item that contains the dropdown menu in use at the moment (the same li that is used for styling the hover state to show the menu). It also adds a class of focused to the anchor that currently has focus. The blur event will need this to handle itself later.

The blur event removes the focused class added earlier, and then checks for another anchor in its menu (indirect sibling) that has the focused class. If there's no indirect siblings with that class, it's safe to close the dropdown by removing the dropdown-visible class. Otherwise, the dropdown is still active and should not be closed (prevents flicker).

With this code, you only need to edit your CSS to add the same styles already being applied to li:hover to li.dropdown-visible, so that the dropdown looks the same when focused as hovered.

That's it. Pretty straight forward, but adds a heap of accessibility.

Note: The code below assumes the following hierarchy:

  • div#top-nav
    • ul
      • li
        • a
        • ul
          • li
            • a

Therefore, the selector '#top-nav ul ul a' selects the very last a element; adjust the selector as necessary to work with your situation.

  1. $('#top-nav ul ul a').each(function () {
  2. $(this).focus(function () {
  3. $(this).addClass('focused');
  4. var menuParent = $(this).closest('ul').parent();
  5. $(menuParent).addClass('dropdown-visible');
  6. });
  7.  
  8. $(this).blur(function () {
  9. $(this).removeClass('focused');
  10. var menuParent = $(this).closest('ul').parent();
  11. if (!$('.focused', parent_li).length) {
  12. $(menuParent).removeClass('dropdown-visible');
  13. }
  14. });
  15. });

Report this snippet  

You need to login to post a comment.