Component · mega-menu
Mega menu
A navigation bar with wide panels on desktop and a full-screen accordion sheet on the phone. Hover intent, real buttons, Esc to close, focus that never gets lost.
Vanilla JS2.4 KBKeyboard + EscPhone sheetReduced motion
Saltmarsh Ferries · Concept
Across the bay in thirty-five minutes.
Use it
Copy the folder mega-menu/ (the .js and .css files) into your project. No build step and no framework.
Behaviour
- Hover opens after a 90 ms intent delay and closes 220 ms after you leave, so crossing the bar diagonally does not flicker panels.
- Click and keyboard work without hover: Enter or Space toggles, ArrowDown moves into the panel, Esc closes and returns focus to the button.
- Phone: full-screen sheet with accordion groups, focus trapped inside, Esc closes, page scroll locked.
- Panels open with a height animation on
grid-template-rows(no fixed heights), links stagger in. prefers-reduced-motion: panels and sheet appear without animation.
Credits
- Navigation patterns studied on ESR Bespoke by NIGHTJAR (Awwwards SOTD Oct 23 2026, "ESR Navigation" element) and Star Atlas by Hello Monday (SOTY 2021, overlay menu). Disclosure pattern per the WAI-ARIA Authoring Practices. Written from scratch.
- Accordion physics from Sujon's Drive guide (MA 8.9). Images are Zyqor concept renders. Saltmarsh Ferries is fictional.
<link rel="stylesheet" href="mega-menu.css">
<nav class="mm" data-mega-menu aria-label="Main">
<div class="mm-bar">
<a class="mm-logo" href="/">Brand</a>
<button class="mm-burger" type="button" aria-expanded="false" aria-controls="mm-list">
<span class="mm-burger-label">Menu</span><i aria-hidden="true"></i></button>
<ul class="mm-list" id="mm-list">
<li class="mm-item">
<button class="mm-trigger" type="button" aria-expanded="false" aria-controls="p1">Routes</button>
<div class="mm-panel" id="p1"><div class="mm-inner"><div class="mm-grid">...columns...</div></div></div>
</li>
<li class="mm-item"><a class="mm-link" href="/about">About</a></li>
</ul>
</div>
<div class="mm-scrim" aria-hidden="true"></div>
</nav>
<script type="module" src="mega-menu.js"></script>| Option | Default | What it does |
|---|---|---|
| .mm-trigger | A button with aria-controls pointing at its .mm-panel. | |
| .mm-grid | 3 columns + feature | Panel layout on desktop; a single column inside the phone sheet. |
| breakpoint | 899px | Change the media queries in the CSS and the mobile() test in the JS together. |