20 CSS Hamburger Menus 09 / 20
Accessible Hamburger Menu (WCAG Compliant)
Full audit-ready pattern: aria-expanded, aria-controls, aria-label, skip link, visible focus rings, focus trap, Escape-to-close, and focus return.
The code
<div class="chm-09">
<div class="chm-09__scene">
<a class="chm-09__skip" href="#chm-09-main">Skip to content</a>
<button class="chm-09__trigger" id="chm-09-trigger" aria-expanded="false" aria-controls="chm-09-menu" aria-label="Toggle navigation menu">
<span class="chm-09__bars" aria-hidden="true"><i></i><i></i><i></i></span>
<span class="chm-09__lbl-open">Menu</span><span class="chm-09__lbl-close">Close</span>
</button>
<div class="chm-09__scrim" id="chm-09-scrim"></div>
<nav id="chm-09-menu" class="chm-09__menu" data-open="false" aria-label="Primary" aria-hidden="true">
<p class="chm-09__grp">Primary navigation</p>
<a href="#" aria-current="page">Home</a>
<a href="#">Services</a>
<a href="#">Case studies</a>
<a href="#">Journal</a>
<a href="#">Contact</a>
</nav>
<main id="chm-09-main" class="chm-09__wrap">
<span class="chm-09__eyebrow">WCAG 2.2 AA</span>
<h1>Navigation everyone can actually use.</h1>
<p class="chm-09__lead">Full keyboard support, focus trapping, Escape to close, and screen-reader semantics baked in. Try it: <strong>Tab</strong> to the button, <strong>Enter</strong> to open, <strong>Esc</strong> to close.</p>
<div class="chm-09__specs">
<code>aria-expanded="false → true"</code>
<code>aria-controls="menu"</code>
<code>aria-label="Toggle navigation menu"</code>
<code>Esc key + focus return + scrim dismiss</code>
</div>
</main>
<div class="chm-09__tag">ACCESSIBLE // 2030</div>
</div>
</div> <div class="chm-09">
<div class="chm-09__scene">
<a class="chm-09__skip" href="#chm-09-main">Skip to content</a>
<button class="chm-09__trigger" id="chm-09-trigger" aria-expanded="false" aria-controls="chm-09-menu" aria-label="Toggle navigation menu">
<span class="chm-09__bars" aria-hidden="true"><i></i><i></i><i></i></span>
<span class="chm-09__lbl-open">Menu</span><span class="chm-09__lbl-close">Close</span>
</button>
<div class="chm-09__scrim" id="chm-09-scrim"></div>
<nav id="chm-09-menu" class="chm-09__menu" data-open="false" aria-label="Primary" aria-hidden="true">
<p class="chm-09__grp">Primary navigation</p>
<a href="#" aria-current="page">Home</a>
<a href="#">Services</a>
<a href="#">Case studies</a>
<a href="#">Journal</a>
<a href="#">Contact</a>
</nav>
<main id="chm-09-main" class="chm-09__wrap">
<span class="chm-09__eyebrow">WCAG 2.2 AA</span>
<h1>Navigation everyone can actually use.</h1>
<p class="chm-09__lead">Full keyboard support, focus trapping, Escape to close, and screen-reader semantics baked in. Try it: <strong>Tab</strong> to the button, <strong>Enter</strong> to open, <strong>Esc</strong> to close.</p>
<div class="chm-09__specs">
<code>aria-expanded="false → true"</code>
<code>aria-controls="menu"</code>
<code>aria-label="Toggle navigation menu"</code>
<code>Esc key + focus return + scrim dismiss</code>
</div>
</main>
<div class="chm-09__tag">ACCESSIBLE // 2030</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Newsreader:opsz,[email protected],400;6..72,500&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');
.chm-09, .chm-09 *, .chm-09 *::before, .chm-09 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.chm-09{
--bg:#fcfbf8;--ink:#1b1b1b;--blue:#1d4ed8;--green:#15803d;--line:#e4e1d8;
min-height:460px;display:grid;place-items:stretch;
font-family:'IBM Plex Sans',sans-serif;background:var(--bg);color:var(--ink);
position:relative;
}
.chm-09__scene{position:relative;width:100%;min-height:460px;height:100%;overflow:hidden}
.chm-09 a:focus-visible,.chm-09 button:focus-visible{outline:3px solid var(--blue);outline-offset:3px;border-radius:6px}
.chm-09__skip{position:absolute;left:-999px;top:12px;z-index:99;background:var(--ink);color:#fff;padding:8px 14px;border-radius:8px;text-decoration:none;font-weight:600;font-size:.85rem}
.chm-09__skip:focus{left:12px}
.chm-09__trigger{position:absolute;top:22px;right:22px;z-index:50;display:flex;align-items:center;gap:10px;
background:#fff;border:2px solid var(--ink);border-radius:14px;padding:10px 14px;cursor:pointer;font-family:inherit;font-weight:600;font-size:.8rem;color:var(--ink);
transition:transform .3s,box-shadow .3s}
.chm-09__trigger:hover{transform:translateY(-2px);box-shadow:4px 4px 0 var(--ink)}
.chm-09__bars{width:20px;height:13px;position:relative;display:inline-block}
.chm-09__bars i{position:absolute;left:0;height:2.4px;width:100%;background:var(--ink);border-radius:3px;transition:transform .45s cubic-bezier(.7,0,.2,1),opacity .3s}
.chm-09__bars i:nth-child(1){top:0}.chm-09__bars i:nth-child(2){top:5.5px}.chm-09__bars i:nth-child(3){top:11px}
.chm-09__trigger[aria-expanded="true"] .chm-09__bars i:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.chm-09__trigger[aria-expanded="true"] .chm-09__bars i:nth-child(2){opacity:0}
.chm-09__trigger[aria-expanded="true"] .chm-09__bars i:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}
.chm-09__lbl-open{display:inline}.chm-09__lbl-close{display:none}
.chm-09__trigger[aria-expanded="true"] .chm-09__lbl-open{display:none}
.chm-09__trigger[aria-expanded="true"] .chm-09__lbl-close{display:inline}
.chm-09__menu{position:absolute;top:0;right:0;height:100%;width:min(320px,84%);z-index:45;background:#fff;border-left:2px solid var(--ink);
transform:translateX(100%);transition:transform .5s cubic-bezier(.16,1,.3,1);padding:88px 24px 24px;display:flex;flex-direction:column}
.chm-09__menu[data-open="true"]{transform:translateX(0)}
.chm-09__grp{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:#777;margin-bottom:12px}
.chm-09__menu a{display:block;font-family:'Newsreader',serif;font-size:1.3rem;color:var(--ink);text-decoration:none;padding:10px 8px;border-radius:8px;transition:background .2s,color .2s}
.chm-09__menu a:hover{background:#eef2ff;color:var(--blue)}
.chm-09__menu a[aria-current="page"]{color:var(--green);font-weight:500}
.chm-09__scrim{position:absolute;inset:0;z-index:40;background:rgba(27,27,27,.35);opacity:0;pointer-events:none;transition:.4s}
.chm-09__scrim[data-show="true"]{opacity:1;pointer-events:auto}
.chm-09__wrap{max-width:700px;margin:0 auto;padding:80px 24px 60px}
.chm-09__eyebrow{display:inline-flex;align-items:center;gap:8px;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--green);font-weight:500;margin-bottom:14px}
.chm-09__eyebrow::before{content:"✓";display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:var(--green);color:#fff;font-size:11px}
.chm-09 h1{font-family:'Newsreader',serif;font-weight:400;font-size:clamp(1.8rem,5vw,3rem);line-height:1.04;letter-spacing:-.01em}
.chm-09__lead{margin-top:16px;font-size:.95rem;line-height:1.65;color:#444;max-width:540px}
.chm-09__specs{margin-top:24px;display:grid;gap:8px;font-family:'IBM Plex Mono',monospace;font-size:11px}
.chm-09__specs code{background:#f0eee7;border:1px solid var(--line);border-radius:6px;padding:7px 11px;color:var(--blue);display:block}
.chm-09__tag{position:absolute;bottom:18px;left:22px;font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.3em;color:#999;z-index:5}
@media (prefers-reduced-motion: reduce){
.chm-09__bars i,.chm-09__menu,.chm-09__scrim,.chm-09__trigger{transition:none !important}
} @import url('https://fonts.googleapis.com/css2?family=Newsreader:opsz,[email protected],400;6..72,500&family=IBM+Plex+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');
.chm-09, .chm-09 *, .chm-09 *::before, .chm-09 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.chm-09{
--bg:#fcfbf8;--ink:#1b1b1b;--blue:#1d4ed8;--green:#15803d;--line:#e4e1d8;
min-height:460px;display:grid;place-items:stretch;
font-family:'IBM Plex Sans',sans-serif;background:var(--bg);color:var(--ink);
position:relative;
}
.chm-09__scene{position:relative;width:100%;min-height:460px;height:100%;overflow:hidden}
.chm-09 a:focus-visible,.chm-09 button:focus-visible{outline:3px solid var(--blue);outline-offset:3px;border-radius:6px}
.chm-09__skip{position:absolute;left:-999px;top:12px;z-index:99;background:var(--ink);color:#fff;padding:8px 14px;border-radius:8px;text-decoration:none;font-weight:600;font-size:.85rem}
.chm-09__skip:focus{left:12px}
.chm-09__trigger{position:absolute;top:22px;right:22px;z-index:50;display:flex;align-items:center;gap:10px;
background:#fff;border:2px solid var(--ink);border-radius:14px;padding:10px 14px;cursor:pointer;font-family:inherit;font-weight:600;font-size:.8rem;color:var(--ink);
transition:transform .3s,box-shadow .3s}
.chm-09__trigger:hover{transform:translateY(-2px);box-shadow:4px 4px 0 var(--ink)}
.chm-09__bars{width:20px;height:13px;position:relative;display:inline-block}
.chm-09__bars i{position:absolute;left:0;height:2.4px;width:100%;background:var(--ink);border-radius:3px;transition:transform .45s cubic-bezier(.7,0,.2,1),opacity .3s}
.chm-09__bars i:nth-child(1){top:0}.chm-09__bars i:nth-child(2){top:5.5px}.chm-09__bars i:nth-child(3){top:11px}
.chm-09__trigger[aria-expanded="true"] .chm-09__bars i:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.chm-09__trigger[aria-expanded="true"] .chm-09__bars i:nth-child(2){opacity:0}
.chm-09__trigger[aria-expanded="true"] .chm-09__bars i:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}
.chm-09__lbl-open{display:inline}.chm-09__lbl-close{display:none}
.chm-09__trigger[aria-expanded="true"] .chm-09__lbl-open{display:none}
.chm-09__trigger[aria-expanded="true"] .chm-09__lbl-close{display:inline}
.chm-09__menu{position:absolute;top:0;right:0;height:100%;width:min(320px,84%);z-index:45;background:#fff;border-left:2px solid var(--ink);
transform:translateX(100%);transition:transform .5s cubic-bezier(.16,1,.3,1);padding:88px 24px 24px;display:flex;flex-direction:column}
.chm-09__menu[data-open="true"]{transform:translateX(0)}
.chm-09__grp{font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:#777;margin-bottom:12px}
.chm-09__menu a{display:block;font-family:'Newsreader',serif;font-size:1.3rem;color:var(--ink);text-decoration:none;padding:10px 8px;border-radius:8px;transition:background .2s,color .2s}
.chm-09__menu a:hover{background:#eef2ff;color:var(--blue)}
.chm-09__menu a[aria-current="page"]{color:var(--green);font-weight:500}
.chm-09__scrim{position:absolute;inset:0;z-index:40;background:rgba(27,27,27,.35);opacity:0;pointer-events:none;transition:.4s}
.chm-09__scrim[data-show="true"]{opacity:1;pointer-events:auto}
.chm-09__wrap{max-width:700px;margin:0 auto;padding:80px 24px 60px}
.chm-09__eyebrow{display:inline-flex;align-items:center;gap:8px;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--green);font-weight:500;margin-bottom:14px}
.chm-09__eyebrow::before{content:"✓";display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:var(--green);color:#fff;font-size:11px}
.chm-09 h1{font-family:'Newsreader',serif;font-weight:400;font-size:clamp(1.8rem,5vw,3rem);line-height:1.04;letter-spacing:-.01em}
.chm-09__lead{margin-top:16px;font-size:.95rem;line-height:1.65;color:#444;max-width:540px}
.chm-09__specs{margin-top:24px;display:grid;gap:8px;font-family:'IBM Plex Mono',monospace;font-size:11px}
.chm-09__specs code{background:#f0eee7;border:1px solid var(--line);border-radius:6px;padding:7px 11px;color:var(--blue);display:block}
.chm-09__tag{position:absolute;bottom:18px;left:22px;font-family:'IBM Plex Mono',monospace;font-size:10px;letter-spacing:.3em;color:#999;z-index:5}
@media (prefers-reduced-motion: reduce){
.chm-09__bars i,.chm-09__menu,.chm-09__scrim,.chm-09__trigger{transition:none !important}
}(() => {
const root = document.querySelector('.chm-09');
if (!root) return;
const trg = root.querySelector('#chm-09-trigger');
const menu = root.querySelector('#chm-09-menu');
const scrim = root.querySelector('#chm-09-scrim');
let open = false;
function setState(s){
open = s;
trg.setAttribute('aria-expanded', s);
menu.dataset.open = s;
menu.setAttribute('aria-hidden', !s);
scrim.dataset.show = s;
if (s) { menu.querySelector('a').focus(); }
else { trg.focus(); }
}
function toggle(){ setState(!open); }
trg.addEventListener('click', toggle);
scrim.addEventListener('click', toggle);
root.addEventListener('keydown', e => {
if (e.key === 'Escape' && open) toggle();
if (e.key === 'Tab' && open) {
const f = [...menu.querySelectorAll('a')];
const first = f[0], last = f[f.length - 1];
if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
}
});
})(); (() => {
const root = document.querySelector('.chm-09');
if (!root) return;
const trg = root.querySelector('#chm-09-trigger');
const menu = root.querySelector('#chm-09-menu');
const scrim = root.querySelector('#chm-09-scrim');
let open = false;
function setState(s){
open = s;
trg.setAttribute('aria-expanded', s);
menu.dataset.open = s;
menu.setAttribute('aria-hidden', !s);
scrim.dataset.show = s;
if (s) { menu.querySelector('a').focus(); }
else { trg.focus(); }
}
function toggle(){ setState(!open); }
trg.addEventListener('click', toggle);
scrim.addEventListener('click', toggle);
root.addEventListener('keydown', e => {
if (e.key === 'Escape' && open) toggle();
if (e.key === 'Tab' && open) {
const f = [...menu.querySelectorAll('a')];
const first = f[0], last = f[f.length - 1];
if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
}
});
})();More from 20 CSS Hamburger Menus
Minimalist 3-Line CSS Menu Icon with Hover EffectsHamburger Menu with Morphing Icon AnimationsFull-Screen Overlay Mobile NavigationSlide-out Sidebar / Off-Canvas NavigationResponsive Navbar with Mobile-Only Hamburger ToggleMinimalist / Floating Hamburger ButtonTailwind CSS Hamburger MenuFull Screen Blur Overlay Hamburger MenuMobile Bottom Nav Bar with Floating HamburgerMulti-Level Dropdown Hamburger Menu (Nested Accordion)Flexbox Navbar with Right-Aligned Hamburger IconCircular Expand / Radial Ripple Mobile Menu
View the full collection →