Menu
A lightweight, accessible navigation and content system built using the native HTML <details> and <summary> elements.
Enhances the default behavior with JavaScript for better usability, keyboard support, and ARIA state management — without relying on external libraries.
- Native
<details>used for dropdown menus in navigation and content. - Automatic closing of
<details>when clicking outside a navigation area. - Keyboard support: pressing
Escapecloses the currently focused<details>. - ARIA attributes (
aria-expanded) synchronized with open/close state. <details>elements can be grouped with a shareddata-groupattribute for mutually exclusive behavior (opening one closes the others), supported in all major browsers.- Responsive hamburger menu with accessible ARIA controls.
- Modern CSS Anchor Positioning used for aligning dropdown menus.
Built with vanilla ES6 JavaScript, focusing on modern syntax and browser APIs.
The JavaScript has been split into separate modules, improving code modularity:
details.js: Handles<details>accessibility and behavior.- Syncs
aria-expandedbetween<summary>and<details>. - Closes dropdowns when clicking outside navigation.
- Supports closing via the
Escapekey and restores focus. - Implements grouped accordion behavior using the
data-groupattribute: when one<details>in a group opens, any others in the same group automatically close.
- Syncs
hamburger-button.js: Toggles the mobile navigation menu.- Updates
aria-expandedon the button. - Switches between hidden/visible menu states.
- Updates the visually hidden text for screen readers.
- Updates
loader.js: See Loader Git repositorytheme.js: Handles theme toggling (light/dark mode) and local storage management.
- Anchor Positioning (
position-anchor) is used to align dropdown menus relative to their<summary>.- In browsers without Anchor Positioning support (e.g., Firefox), the layout gracefully falls back to a standard flow layout, preserving an unbroken user experience.
- Uses media query range syntax for responsive breakpoints.
- Mobile-first design, with progressive enhancements for larger viewports.
- Dropdown menus adapt to available space without JavaScript intervention.
- ARIA attributes (
aria-expanded) dynamically updated on all<summary>elements. - Escape key support: closes the open
<details>and returns focus to its<summary>. - Clicking outside a
<nav>closes only its dropdown menus. - Mobile hamburger menu includes
aria-controlsandaria-expandedfor screen reader support. - Semantic HTML structure (
<header>,<nav>,<main>,<details>,<summary>) aids navigation for assistive technologies.
If JavaScript is disabled, the loader animation, theme-toggler and mobile menu cease to function. However, all content remains accessible.
As of September 2025, Caniuse reports that the following browsers/platforms support anchor positioning:
- Chrome v.140
- Edge v.140
- Opera v.122
- Chrome for Android v.139
- Safari on IOS v.26
- Android Browser v.139
Caniuse reports that "All major browser engines are working on implementing this spec".
Note: unsupported browsers/platforms will display the default details behaviour.
The anchor positioning code for the main navigation comes from a Codepen by Ryan Trimble. My only changes were:
- Changing IDs to classes
- Adding
position-try-fallbacks: flip-block, flip-inlineto the target's::details-content - Making both targets
position-area: block-end center
The application includes a dark mode and light mode toggle:
- The current theme state is stored in local storage and applied automatically on page reload.
- Accessible buttons with appropriate ARIA attributes are used to improve usability.
Important
Remember to change const LOCAL_STORAGE_PREFIX in js-modules/theme.js to a unique identifier.
The application has been tested on the following platforms and browsers:
- Operating System: Windows 10/11
- Browsers:
- Google Chrome (full support, including Anchor Positioning)
- Mozilla Firefox (no Anchor Positioning support yet, but layout gracefully falls back to default
<details>behavior) - Microsoft Edge (full support, including Anchor Positioning)
The layout and functionality have been verified in both browser and device simulation views to ensure responsiveness and usability.
- Clone or download the repository to your local machine.
- Open the project folder and start a simple HTTP server (e.g., using
Live Serverin VS Code or Python'shttp.servermodule). - Open the project in a modern browser (e.g., Chrome, Firefox, or Edge).
If you want to deploy a minified version of this project to GitHub Pages, read on.
Run this once in your project root to install dev dependencies:
npm installImportant
Any assets not described in package.json must be added. In the current project we don't have an img folder. If you create one and add images to it, you have to add this to copy:assets, e.g.
"copy:assets": "shx cp -r site.webmanifest favicon.ico favicon-16x16.png favicon-32x32.png apple-touch-icon.png android-chrome-192x192.png android-chrome-512x512.png docs/",
"copy:assets": "shx cp -r img site.webmanifest favicon.ico favicon-16x16.png favicon-32x32.png apple-touch-icon.png android-chrome-192x192.png android-chrome-512x512.png docs/",
etc, etc.
Then in the terminal, run:
npm run buildOnce you've created a repository and pushed the files,
- go to
https://github.com/[your-name]/[your-project-name]/settings/pages. - Under "Build and deployment > Branch" make sure you set the branch to
mainand folder to/docs. - Click "Save".
Note
For a detailed description of the build process, configuration files and npm packages see my GitHub Pages Optimised Build.