Zack Pyle released a really nice plugin to re-enable the native menu management system. It produces an easy-to-use loop function but leaves the styling and JS functionality to you. Here are the basics for a dropdown to work correctly.
Note: This assumes you are just using Zacks’ sample code.
JavaScript
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.site-nav').forEach((nav) => {
const triggers = nav.querySelectorAll('.site-nav__dropdown-trigger');
const closeDropdown = (trigger) => {
const submenuId = trigger.getAttribute('aria-controls');
const submenu = submenuId ? document.getElementById(submenuId) : null;
trigger.setAttribute('aria-expanded', 'false');
if (submenu) {
submenu.classList.remove('is-open');
}
};
const openDropdown = (trigger) => {
const submenuId = trigger.getAttribute('aria-controls');
const submenu = submenuId ? document.getElementById(submenuId) : null;
trigger.setAttribute('aria-expanded', 'true');
if (submenu) {
submenu.classList.add('is-open');
}
};
const closeAllDropdowns = (exceptTrigger = null) => {
triggers.forEach((trigger) => {
if (trigger !== exceptTrigger) {
closeDropdown(trigger);
}
});
};
triggers.forEach((trigger) => {
trigger.addEventListener('click', () => {
const isExpanded = trigger.getAttribute('aria-expanded') === 'true';
closeAllDropdowns(trigger);
if (isExpanded) {
closeDropdown(trigger);
} else {
openDropdown(trigger);
}
});
trigger.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeDropdown(trigger);
trigger.focus();
}
});
});
nav.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
closeAllDropdowns();
}
});
document.addEventListener('click', (event) => {
if (!nav.contains(event.target)) {
closeAllDropdowns();
}
});
});
});CSS
.site-nav {
display: flex;
flex-direction: column;
gap: var(--card-gap);
padding: var(--space-xs);
& .site-nav__dropdown {
opacity: 0;
transform: translateY(-0.5rem);
display: none;
transition:
opacity 0.2s ease-in,
transform 0.2s ease-in,
display 0.2s allow-discrete;
}
& .site-nav__dropdown.is-open {
display: flex;
opacity: 1;
transform: translateY(0);
flex-direction: column;
@starting-style {
opacity: 0;
transform: translateY(-0.5rem);
}
}
& .site-nav__dropdown-trigger[aria-expanded='true'] .site-nav__chevron {
rotate: 180deg;
}
}
Share Your Thoughts