Skip to content
Knsept
Free playbook

Animated menu button

A hamburger icon that morphs into an X and opens a menu. Correct aria-expanded, Escape to close, focus handled.

CSSJavaScriptUI Widgets Updated Oct 23, 2026
Live demo Reduced motion is on, so effects are toned down
<nav class="menu-demo" aria-label="Main">
  <button class="menu-button" type="button" aria-expanded="false" aria-controls="demo-menu">
    <span class="menu-icon" aria-hidden="true"><i></i><i></i><i></i></span>
    <span class="menu-text">Menu</span>
  </button>
  <ul class="menu-list" id="demo-menu" hidden>
    <li><a href="#docs">Docs</a></li>
    <li><a href="#library">Library</a></li>
    <li><a href="#blog">Blog</a></li>
  </ul>
</nav>

One attribute does all the work: aria-expanded. The script flips it, and the CSS reads it to morph the icon: the middle bar fades, and the top and bottom bars move to the center and rotate ±45° into an X. Screen readers hear "Menu, collapsed" or "expanded" from the same attribute, so the visuals and the announcement can never disagree.

The visible text changes from "Menu" to "Close" too, so the button is labelled for sighted keyboard users. Escape closes the menu and puts focus back on the button, and clicking outside closes it.

With reduced motion on, the icon still morphs, just faster, and the menu appears without sliding.

More from the library

Navigation live

Smooth accordion

A FAQ accordion built on native details/summary, with a smooth open and close animation and an optional one-open-at-a-time mode.

Navigation live

Sliding tabs

Accessible tabs with an indicator that glides between them. Full keyboard support, works at any width.

Scroll & motion live

Count-up stats

Numbers that count up when they scroll into view, with easing and formatting. A quicker count with reduced motion.