Accessible Dropdown Navigation (Handling Focus with jQuery)


/ Published in: JavaScript
Save to your folder(s)

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.


Copy this code and paste it in your HTML
  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


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.