Atomic Smash homepage splash

Build a keyboard-accessible navigation bar with drop-down menus

Words by George HieronJuly 25, 2018

An illustration of the 'tab' keyboard key

A mouse or trackpad is the most common way by which most of us control their computers, and for those who work at a computer, this is likely peppered with a fair few keyboard shortcuts. However, it is worth remembering that there are many people who, for various reasons, use the keyboard as their primary method of navigating their machine to improve its accessibility for them. It’s good to keep this in mind when building websites, particularly regarding the main navigation bar.

Here's one I made earlier...

Throughout this post I will refer to this simple CodePen I have made, to demonstrate how a menu with drop-down items can be made keyboard-accessible.

See the Pen Accessible Nav by AtomicSmash (@AtomicSmash) on CodePen.

It’s quite a normal arrangement of <ul>s and <li>s with <a>s inside. If you comment out all of the SCSS in the CodePen example and begin using the tab key to navigate through the menu, you will see that, as all of the anchors are visible, they all receive focus clearly and can be triggered with the return/enter key.

Accessible menu with no CSS applied.

With no CSS involved, our nav is very ugly, but perfectly accessible!

However, since we want our nested lists to be hidden and then revealed when necessary, this poses an accessibility problem – the tab key will set the focus correctly and the links will be usable, but since the menu items are hidden, there is no clear visual indication as to where you are in the list.

Find your inner focus 🙏

Enter the :focus-within pseudo-class; this allows you to target an element that contains an element which has been focused on. Here, I have used :focus-within on the top-level <li>s that contain nested drop-downs, so that they can receive the appropriate styles when their child anchors receive focus. Try commenting out lines 95 to 105 in the example; you will see that, whilst tabbing through the nested menu is functional, the user would be completely lost as soon as they get past the top-level of ‘About’. The highlight colour disappears, and there is no indication of when you will emerge from the other side of the menu.

Accessible menu with CSS applied, showing an open drop-down menu.

Now that our CSS is applied, including the use of :focus-within, we can access our drop-down menu items with the keyboard.

It’s important to note that the :focus-within rules, whilst the same as those for :hover and :focus, are written independently. This creates duplication, but since :focus-within is not supported by Edge or Internet Explorer, the rules for:hover, :focus, and :focus-within cannot be chained, or the whole set fails to work in those browsers. Although this means that in IE and Edge, the navigation is not keyboard-accessible, is still at least functional.

A finishing touch

As a final touch to improve the user experience of the navigation, I have implemented classes to left- or right-align the content of the drop-down menus. This is useful depending on where your menu is positioned on your site, and where the drop-down parent(s) sit within it. It is simply achieved by positioning the drop-down menu items (.dropdown__content) absolutely, and given a top value of the height of the main header. Using left and right positioning values allows the drop-down content to sit to either the left or right edge of its parent, and a width value of 100vw used in conjunction with :before and :after pseudo-elements ensures that the drop-down content appears to span the entire width of the viewport, matching the header.

Accessible menu with a right-aligned drop-down menu open.

With our nav positioned this close to the edge of the viewport, it's likely that any drop-down menu items would overflow the viewport if not right-aligned.

Hopefully, you have found this insight useful for the accessibility of your builds. To learn more about keyboard navigation, check this page out: https://webaim.org/techniques/keyboard/. If you found this helpful, or perhaps you’ve approached this issue in a different way, leave a comment below!

Go back to top

Keep up to date with Atomic news