Skip to Content
Component ExamplesNavigation Menus

Overview

Navigation is one of the most critical parts of a page for keyboard and screen reader users. Two common mistakes are: misusing ARIA menubar/menuitem roles (which carry desktop application semantics), and building dropdown menus without keyboard support. The correct pattern is a <nav> landmark with a list of links, and a disclosure button for submenus.

WCAG Criteria:

Key requirements:

  • Use <nav aria-label="..."> to create a navigation landmark
  • Use <ul> and <li> to provide list structure
  • Use aria-current="page" on the link for the current page
  • For dropdowns, use a <button aria-expanded> followed by a hidden <ul> — not role="menu"
  • role="menubar" and role="menuitem" are for application menus (like a File/Edit menu bar), not site navigation

Semantic Nav with Disclosure vs. ARIA Menubar Misuse

Inaccessible
<!-- menubar/menuitem roles imply desktop app behavior — wrong for site nav --> <div role="menubar"> <div role="menuitem"><a href="/">Home</a></div> <div role="menuitem"><a href="/about">About</a></div> <div role="menuitem"> <a href="/products">Products</a> <div role="menu"> <div role="menuitem"><a href="/products/shoes">Shoes</a></div> <div role="menuitem"><a href="/products/bags">Bags</a></div> </div> </div> <div role="menuitem"><a href="/contact">Contact</a></div> </div>
Live Preview

Note: role="menubar" is misused here — these are navigation links, not an application menu.

Accessible
<nav aria-label="Main"> <ul style="list-style:none;display:flex;gap:4px;margin:0;padding:0;"> <li> <a href="/" aria-current="page">Home</a> </li> <li> <a href="/about">About</a> </li> <li> <!-- Disclosure button controls submenu — no menuitem role needed --> <button aria-expanded="false" aria-controls="nav-products-submenu" onclick=" var expanded = this.getAttribute('aria-expanded') === 'true'; this.setAttribute('aria-expanded', String(!expanded)); var menu = document.getElementById('nav-products-submenu'); if (!expanded) { menu.removeAttribute('hidden'); } else { menu.setAttribute('hidden', ''); } " > Products </button> <ul id="nav-products-submenu" hidden> <li><a href="/products/shoes">Shoes</a></li> <li><a href="/products/bags">Bags</a></li> </ul> </li> <li> <a href="/contact">Contact</a> </li> </ul> </nav>
Live Preview

Resources