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:
- 2.4.1 Bypass Blocks — navigation must be skippable (skip links or landmarks)
- 4.1.2 Name, Role, Value — interactive elements must expose correct roles
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>— notrole="menu" role="menubar"androle="menuitem"are for application menus (like a File/Edit menu bar), not site navigation
Main 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