How to Develop an Accessible Navigation Menu
While recently taking a course on Underscores, a WordPress starter theme, on Lynda.com, I came across Superfish, a handy jQuery plugin that greatly helps in the development of accessible navigation menus.
Among the features of Superfish are touch device support, timed mouseout delay to avoid hiding sub-menus appearing on hover too soon, and keyboard accessibility. There’s also the option of creating custom callback functions to perform additional actions on top of the plugin.
I had been using a combination of Modernizr (for touch device detection) along with some custom Javascript to get one of my site’s drop-down menu to work well on both mobile and desktop devices, but admittedly, I hadn’t thought much about accessibility during initial development. Revisiting the menu to make it accessible took a bit of time but I definitely learned a lot and it was well worth the effort. Below are the steps I took to create an accessible menu.
Prerequisites
Before implementing Superfish, I overhauled the navigation menu that I had, making it a simple CSS-based menu with hover effects to display the sub-menu. As described in the Superfish Getting Started page, this means that the menu will gracefully degrade in cases where Javascript is not available.
Download Superfish and its Dependencies
Superfish is a jQuery plugin, and in order to get the best support for touch interactions on Android browsers and IE10, I also followed the recommendation in the docs to use the hoverIntent jQuery plugin. All together, I needed to add the following to my project, including them in the given order in my HTML:
- jQuery
- hoverIntent
- superfish
Create a Superfish Settings File
As described in the docs, a settings file is needed to initialize Superfish with the features that you want to use. My case was pretty straightforward. I set a small 400ms delay to prevent the menu from closing too early after mouseout, set the speed animation to ‘fast’, and disabled drop shadows and CSS arrows since I decided not to use the optional Superfish CSS file.
Since I wanted to show my entire sub-menu at once upon hover or keyboard focus (instead of showing the nested unordered lists underneath it individually as they were focused on), I also set popUpSelector
to the CSS class assigned to the parent unordered list for the sub-menu, which was sub-menu
in my case. Superfish is initialized with the name of the CSS selector that’s assigned to the navigation menu itself, which was nav-menu
in my case. These settings resulted in the following file:
/*
* Custom Superfish settings
*/
jQuery(document).ready(function() {
jQuery('ul.nav-menu').superfish({
popUpSelector: 'ul.sub-menu',
delay: 400,
speed: 'fast',
dropShadows: false,
cssArrows: false
});
});
Concat and Minify Javascript
For speedier page load times, I concatenated the hoverIntent.js
, superfish.js
, and superfish-settings.js
files into one file and then minified the resulting file using Grunt. Then I just had one Javascript file to include in my HTML after jQuery (at the end of thesection).
Add ‘Skip To Content’ Link
In addition to Superfish, I added a ‘skip to content’ link at the beginning of my navigation menu to allow screen readers to break out of the navigation menu and skip to the main content on the page, leveraging from what I’ve seen in WordPress. By adding an anchor tag within the main content section, clicking or selecting the ‘skip to content’ link scrolls the page down to the main content. Note that some CSS changes were needed to hide the ‘skip to content’ text from view (hence the need for the screen-reader-text
CSS class) and to add some styling to the ‘skip to content’ box when it is focused on by the keyboard:
<nav>
<h1>
<a href="index">Sheelahb Gallery</a></h1>
<a class="screen-reader-text" href="#main">Skip to main content</a>
<ul class="nav-menu">
<li><a href="index">Home</a></li>
<li class="nav-dropdown"><a href="#">Galleries</a>
<ul class="sub-menu">
<li>Photography
<ul>
<li class="menu-item">
<a href="landscapes">Landscapes</a>
</li>
....
</nav>
<div id="mainWrapper">
<div class="main">
Testing
I tested the navigation menu using the very handy Browser-Sync Grunt plugin, testing on both mobile and tablet devices and desktops and it works very well. I also tested the menu using the ChromeVox Chrome extension which functions as a screen reader.
Final Result
The navigation menu can be seen live on my SheelahbGallery site, and I created a slightly simplified example on codepen, embedded below.
See the Pen Accessible navigation menu by Sheelah (@sheelah) on CodePen.