Accessible Hamburger Menu
Adding a link to Google to test keyboard support when the nav is open.
The hamburger bars are 3 bars stacked in a vertical column. When the button is activated, the bars transform into the "X". The middle bar disappears and the top and bottom bars transform by rotating 135 degrees in to the y axis creating the X. To achieve this, you only need a container with 3 spans:
<button class="menu-btn" id="menu-btn" aria-expanded="false" aria-label="Menu">
<span></span>
<span></span>
<span></span>
</button>
CSS:
.menu-btn {
width: 30px;
height: 20px;
position: relative;
cursor: pointer;
}
.menu-btn span {
display: block;
position: absolute;
height: 3px;
width: 100%;
background: black;
border-radius: 9px;
transition: .25s ease-in-out;
}
/* Position the bars */
.menu-btn span:nth-child(1) { top: 0px; }
.menu-btn span:nth-child(2) { top: 8px; }
.menu-btn span:nth-child(3) { top: 16px; }
/* The "Open" State */
.menu-btn.open span:nth-child(1) {
top: 8px;
transform: rotate(135deg);
}
.menu-btn.open span:nth-child(2) {
opacity: 0;
left: -60px;
}
.menu-btn.open span:nth-child(3) {
top: 8px;
transform: rotate(-135deg);
}
JS:
const menuBtn = document.getElementById('menu-btn');
menuBtn.addEventListener('click', () => {
menuBtn.classList.toggle('open');
});
Let's add some JS to update the aria-expanded value when activated:
const menuBtn = document.getElementById('menu-btn');
menuBtn.addEventListener('click', () => {
const isOpen = menuBtn.classList.toggle('open');
menuBtn.setAttribute('aria-expanded', isOpen);
});
Demo:
Note: The demo is just to illustrate the transformation. The widget at the beginning of the page is the fully working control.
The rest is magic...