The component
A navigation menu that opens on hover, built from divs. It looks right, it demonstrates well, and it cannot be used with a keyboard, cannot be announced, and disappears the moment somebody with a tremor moves the pointer a few pixels.
This is the most common broken component on the web, and rebuilding it uses every lesson in this course.
What it has to become
- A real
<button>that opens and closes it, witharia-expandedkept true andaria-controlspointing at the panel. - A real list of real links inside the panel — not divs with click handlers.
- Opening and closing on click, not hover. Hover may open it as well, but it must never be the only way.
- Escape closes it, and focus returns to the button.
- When it is closed the links are not reachable by Tab; when it is open they are.
- Everything named, and the button’s name says what it opens.
Why not hover
Hover cannot be triggered by a keyboard, is unreliable with a touch screen, and requires a steady pointer for as long as the menu is open. WCAG 2.1 added a criterion for exactly this: content that appears on hover must be dismissible, hoverable and persistent — which a click-to-open disclosure gets for free.
If the design insists on hover, add it on top of the click behaviour, with a delay before it closes.
The order to work in
Semantics first — put the right elements in. Then state — aria-expanded, and hiding the panel properly with hidden rather than opacity: 0, which leaves everything reachable. Then keys — Escape, and focus back. Then check it with Tab, then with a screen reader.
That order matters: half the ARIA you were about to write turns out to be unnecessary once the elements are right.