Menus that keep focus where it belongs

Choose the right keyboard model for a navigation overlay, manage focus on open and close, and prevent visitors reaching hidden content.

TL;DR

  • A navigation overlay that blocks the page behaves as a modal: move focus in, make the background inert and return focus when it closes.
  • Use a real button with aria-expanded, and don't give ordinary site links role=menu.
  • Test with the keyboard only, at zoom, with reduced motion, and by closing the menu during its opening animation.

Summarise this article with

A full-screen menu changes more than what’s visible. It also changes which parts of the page a visitor should be able to reach.

If a keyboard user can tab through links behind the overlay, the menu isn’t finished. If closing it leaves focus inside hidden content, the visitor may lose their place. These problems are easy to miss when you only test with a mouse. For the wider set of checks, see Accessibility checks a designer can do in an afternoon.

Decide whether it’s a disclosure or a modal

A small navigation panel that expands within the page can use a disclosure pattern. Its button exposes whether the panel is open, and the normal tab order continues through the page.

A navigation overlay that makes the rest of the interface unavailable behaves as a modal. Opening it should move focus into the overlay, and background controls should be unavailable until it closes.

Don’t give every navigation list role="menu". That ARIA role introduces a different interaction model, the one used for application-style menus. Ordinary site links usually belong in a nav with normal links.

The visual design alone doesn’t determine the semantics. Decide what visitors can do while the panel is open, then implement that behaviour consistently.

Use a real button to open it

The opener needs a clear accessible name and an exposed state:

<button type="button" aria-expanded="false" aria-controls="site-navigation">
  Open menu
</button>

Update aria-expanded whenever the navigation changes state. If the label becomes “Close menu”, change the accessible name as well. A screen reader shouldn’t announce an old action while the icon has already changed.

Avoid a clickable div unless there’s a strong reason. A button already supports the activation keys people expect.

Opening needs a deliberate focus destination

For a short overlay, the close button or the first navigation link can be a sensible initial focus target. For more complex content, think about what helps the visitor understand where they’ve arrived.

Make the target visible before moving focus to it. Don’t focus a link and then run a long animation that keeps it offscreen. Reduced-motion preferences shouldn’t leave visitors waiting through a reveal sequence. The motion trade-offs are covered in Motion that helps a marketing site, and motion that gets in the way.

A native dialog opened with showModal() supplies useful modal behaviour, including an inert background. It still needs an appropriate name, a visible close control and testing with your real content.

Custom overlays need their own complete focus strategy. Setting aria-modal="true" describes the behaviour, but it doesn’t implement it.

The background must stop participating

For a modal overlay, inert can remove background regions from interaction and from the accessibility tree. Apply it to the regions behind the overlay, not to a parent that also contains the menu.

If an element was already inert for another reason, preserve that state when the menu closes. A menu script shouldn’t accidentally unlock something a separate feature meant to keep disabled.

Decide whether background scrolling should stop too. A scroll lock has to release reliably after Escape, a link activation, a close-button click and any navigation transition.

Closing should return people somewhere useful

Escape should close a modal navigation overlay. Closing without navigating should normally return focus to the opener, provided that button still exists and is usable.

Following a link is different. When the visitor moves to another page, the destination’s navigation and focus behaviour take over. Returning focus to the old opener after an in-page link may also be wrong, because the intended section needs its own consideration.

Avoid one generic close handler that treats every reason for closing the same way.

A five-minute keyboard check

Open the menu with the keyboard. Move forwards and backwards through every control. Check that focus stays visible, that the background is unavailable when it should be and that Escape works.

Repeat from a different opener if there is more than one. Try a narrow screen, zoomed text and reduced motion. Use a screen reader to confirm the menu has a useful name and that its open state is announced.

Finally, close the menu during its opening animation. Rapid interactions often reveal stale classes and hidden focus that a slow walkthrough misses. The script side of this is covered in Custom code snippets in Webflow without breaking the Designer.

References

  • Interaction design
  • Accessibility