Mega Menu A11Y
title: "Accessible Mega Menu — Complex Dropdown Navigation with Keyboard Support" description: "Learn how to build accessible mega menus with multiple columns, keyboard navigation, focus management, and screen reader announcements for complex hierarchies." weight: 11 date: 2026-06-28 lastmod: 2026-06-28 tags: [accessibility, navigation]
Accessible mega menus provide navigation for complex site structures with multiple columns and categories, using proper ARIA and keyboard support.
## What You'll Learn
How to build mega menus that work with keyboard navigation, manage focus within columns, and communicate structure to screen readers.
## Why It Matters
Mega menus present many navigation options at once. Without accessibility, keyboard users cannot access subcategories, and screen reader users hear an overwhelming list of links.
## Real-World Use
A large e-commerce site has a mega menu with Categories, Brands, and Deals. A keyboard user tabs to "Products" (the top-level trigger), the menu opens, and they use arrow keys and Tab to navigate columns. Escape closes the menu.
## Mega Menu Structure
```html
<nav aria-label="Main">
<ul>
<li>
<button aria-expanded="false" aria-haspopup="true"
aria-controls="products-menu">
Products
</button>
<div id="products-menu" role="region" aria-label="Products menu" hidden>
<div role="group" aria-labelledby="cat-heading">
<h3 id="cat-heading">Categories</h3>
<ul>
<li><a href="/laptops">Laptops</a></li>
<li><a href="/phones">Phones</a></li>
<li><a href="/accessories">Accessories</a></li>
</ul>
</div>
<div role="group" aria-labelledby="brand-heading">
<h3 id="brand-heading">Brands</h3>
<ul>
<li><a href="/brand-x">Brand X</a></li>
<li><a href="/brand-y">Brand Y</a></li>
</ul>
</div>
</div>
</li>
</ul>
</nav>
JavaScript
const trigger = document.querySelector('[aria-controls="products-menu"]');
const menu = document.getElementById('products-menu');
trigger.addEventListener('click', function() {
const expanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', !expanded);
menu.hidden = expanded;
if (!expanded) {
menu.querySelector('a').focus();
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && !menu.hidden) {
menu.hidden = true;
trigger.setAttribute('aria-expanded', 'false');
trigger.focus();
}
});
Common Mistakes
1. Menu opens only on hover
Keyboard users cannot hover. The menu must open on focus or click.
2. No Escape to close
Users must be able to close the mega menu with the Escape key and return focus to the trigger.
3. Focus trapped inside menu
Tab should cycle through links in the menu. Shift+Tab should go back to the trigger.
4. No aria-expanded on trigger
The trigger button must have aria-expanded to communicate open/closed state to screen readers.
5. Too many links without organization
Group mega menu links into categories with headings. Each category group needs a label.
Practice Questions
1. What attribute indicates the menu is open? aria-expanded="true" on the trigger button communicates the open state.
2. What key closes the mega menu? Escape closes the menu and returns focus to the trigger button.
3. How do you organize mega menu content for screen readers? Use role=group with aria-labelledby for each category column.
Challenge: Build a mega menu with three category columns and 5-6 links each. Implement keyboard navigation, Escape to close, and focus management.
FAQ
Mini Project
Create a mega menu for a tech store with columns: Laptops, Phones, Accessories, and Deals. Each column has 4-5 links. Implement full keyboard support.
What's Next
Learn about Hamburger Menu accessibility and how to implement mobile navigation patterns that work for all users.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro