Fully accessible dropdown with keyboard navigation and ARIA support
Dropdown used in navigation with multiple items
Comparison of dropdown menu without animation and with CSS Grid animation
Menu shows/hides instantly
Smooth animation using grid-template-rows is default
Animation speed can be set using CSS custom properties (variables).
You can set them globally in CSS or inline using the style attribute.
<div data-dropdown>
<button data-dropdown-button>
Button Text
<span class="dropdown__arrow"></span>
</button>
<div data-dropdown-menu data-no-animation>
<div>
<div>
<a href="#" data-dropdown-item>Item 1</a>
<a href="#" data-dropdown-item>Item 2</a>
</div>
</div>
</div>
</div>
<!-- Animations are default, no need to add any attribute -->
<div data-dropdown>
<button data-dropdown-button>
Button Text
<span class="dropdown__arrow"></span>
</button>
<div data-dropdown-menu>
<!-- Two wrapper divs REQUIRED for animations -->
<div>
<div>
<a href="#" data-dropdown-item>Item 1</a>
<a href="#" data-dropdown-item>Item 2</a>
</div>
</div>
</div>
</div>
Important for animations:
β’ Animations are default - automatically enabled
β’ Content in data-dropdown-menu must be wrapped in two <div> wrappers
β’ Animation uses modern CSS Grid approach (grid-template-rows: 0fr β 1fr)
β’ Works without needing to know menu height beforehand
β’ Better alternative to transform and fixed height animations
β’ Animation speed: use CSS custom property --a11y-dropdown-duration (default: 0.2s)
β’ Easing function: use CSS custom property --a11y-dropdown-easing (default: ease)
β’ Automatic prefers-reduced-motion support
<!-- Inline using style attribute -->
<div data-dropdown style="--a11y-dropdown-duration: 0.5s;">
<button data-dropdown-button>Menu</button>
<div data-dropdown-menu>
<div><div>...</div></div>
</div>
</div>
<!-- Custom easing -->
<div data-dropdown
style="--a11y-dropdown-duration: 0.3s; --a11y-dropdown-easing: ease-in-out;">
<!-- dropdown menu -->
</div>
<!-- Or globally in CSS -->
<style>
:root {
--a11y-dropdown-duration: 0.25s;
--a11y-dropdown-easing: cubic-bezier(0.4, 0, 0.2, 1);
}
</style>
<!-- Disable animations -->
<div data-dropdown-menu data-no-animation>
<!-- menu without animations -->
</div>
import { initDropdowns } from './a11y-kit/a11y-dropdown.js';
// Initialize after DOM is ready
document.addEventListener('DOMContentLoaded', () => {
initDropdowns();
});
// Import short alias
import { Dropdown } from './a11y-kit/a11y-dropdown.js';
// Use like Bootstrap
const dropdown = new Dropdown(element, {
closeOnSelect: true,
closeOnOutsideClick: true,
closeOnEscape: true,
onOpen: (instance) => console.log('Opened'),
onClose: (instance) => console.log('Closed'),
onSelect: (item, index) => console.log('Selected:', item)
});
npm install accessible-kit
// Import only what you need (best for tree-shaking)
import { initDropdowns, Dropdown } from 'accessible-kit/dropdown';
// Initialize after DOM is ready
document.addEventListener('DOMContentLoaded', () => {
initDropdowns(); // Auto-init all dropdowns
// OR create instances manually
const dropdown = new Dropdown(element, options);
});