How to build Accessible Navigation Menus with the Popover API
Navigation menus are an essential part of every website. They're usually placed in the header and provide an overview of a website's page hierarchy. They enable users to gain an overview of the content and to quickly navigate to main sections of the website.
Many websites use fly-out (or drop-down) menus, where certain menu items open submenus on hover or click. Often, these menus offer very poor accessibility for screen reader and keyboard users. But we can do better!
I'll show you how to leverage the power of modern web features like the Popover API to easily create an accessible fly-out menu.
Photo: © Valentin Antonucci / pexels.com
What we want to achieve
Our navigation menu should be easy to use for different user groups:
- The submenus should appear on top of the site content and should not disappear immediately after the mouse has left the clickable area.
- Screen reader users require meaningful markup to understand and operate the navigation menu.
- Keyboard users should be able to operate the menu using the keyboard alone.
Demo: Accessible Navigation Menu
I've created a CodePen demo of an accessible navigation menu using the Popover API. Be sure to open the demo on a desktop screen or tablet in landscape mode to see the fly-out menu. On smaller devices, the demo will display a mobile menu instead.
Photo: © Alexander Lehner
The navigation menu is easy to use for mouse, keyboard, and screen reader users. Let's examine the key elements.
Meaningful Markup
We use the nav
element to convey the role of the navigation menu. The menu items are placed
inside an unordered list (ul
element). This allows assistive technologies to announce the number
of items in the menu and provide corresponding navigation functionality.
<nav class="main-nav">
<ul>
<li>
<button popovertarget="nav-panel-solutions" type="button">Solutions</button>
<div id="nav-panel-solutions" popover>...</div>
</li>
<li><a href="#">Products</a></li>
<li>...</li>
<li>...</li>
</ul>
</nav>
The list items either contain a direct link to a subpage, or they contain a button
element
that opens a submenu which uses the popover
attribute. The button is connected to the popover
content via the popovertarget
attribute.
One of the great advantages of the Popover API: It automatically conveys to assistive technologies whether the submenu navigation is presently collapsed or expanded. You should read the article “On popover accessibility: what the browser does and doesn’t do” for more information.
Avoid the menu
role
As you can see in my demo, I'm not using the menu
and menuitem
roles
in my navigation menu. This is on purpose! These ARIA roles are only inteded for menu widgets that behave like native
operating system menus.
Go read the article “Don’t Use ARIA Menu Roles for Site Nav” by Adrian Roselli for a detailed explanation.
Visual Placement
When a submenu is opened, it will automatically appear on the top layer, a separate layer that sits on top of all other layers displayed in the web document. You only need to take care of the placement and size of the submenu:
header nav.main-nav [popover] {
top: var(--header-height);
margin: 0;
width: 100%;
}
The default placement of popover content is in the center of the screen. To place our submenus right beneath the header,
we set top
to the height of the header and remove any margin
. Next, we
set width
to 100%
to make the submenu cover the whole width of the page.
Keyboard Operability
You can use the TAB
key to focus the links and buttons in the navigation menu. After opening a
submenu, its content will be next in the focus order. Pressing the ESC
key will close the submenu
and automatically return focus to the trigger button. All thanks to the mighty Popover API! 🤩
Light-dismiss of Submenus
Another baked in feature of the Popover API is light-dismiss: Clicking outside of the submenu area will close the submenu
and return focus to the trigger element. No need to mess around with focusout
events in JavaScript.
Useful Resources
- Navigation Menus Tutorial (W3C)
- Disclosure Pattern (ARIA APG)
- Example Disclosure Navigation Menu (ARIA APG)
- Popover API (MDN)
Posted on