Loading Developer Playground

Loading ...

Skip to main content
ARIA ROLEComposite RolesCommand surfaceArrow navigationSupports submenus

menu

Presents a list of actions or commands. Menus often appear as context menus, dropdowns, or secondary command palettes.

Live Example

Command Menu Button

Menu surface triggered by a button with Arrow key navigation and shortcuts.

Purpose

Expose grouped actions that relate to the same UI surface.

Structure

Contains menuitem, menuitemcheckbox, or menuitemradio elements.

Trigger

Often paired with a menu button that sets aria-expanded and focus management.

When to Use

1

Context menus

Right-click or long-press menus for file operations, editing, or row-level actions.

2

Dropdown buttons

Buttons with adjacent caret toggles that show additional commands.

3

Nested editing menus

Rich text editors or design tools with multi-level command structures.

Required Structure

Trigger button

A button with aria-haspopup="menu" and aria-controls referencing the menu element.

Menu container

role="menu" requires an accessible name and should stay mounted for assistive tech discovery.

Menu items

Use role="menuitem", "menuitemcheckbox", or "menuitemradio". Apply aria-checked where relevant.

Keyboard Interaction Model

ActionKeysResult
Open menuEnter / Space / ArrowDownOpens the menu from its trigger and focuses the first item.
Move focusArrowDown / ArrowUpMoves between items without closing the menu.
Jump to edgesHome / EndMoves to the first or last menu item.
ActivateEnter / SpaceRuns the command for the focused item.
Close menuEscape / Alt + ArrowUpDismisses the menu and returns focus to the trigger.
Submenu navigationArrowRight / ArrowLeftRight opens a submenu when present; Left closes the current submenu.

Required States & Properties

aria-orientationOptional

Set to vertical (default) or horizontal depending on layout.

aria-haspopupOptional

Buttons or menu items that open submenus should advertize aria-haspopup="menu".

aria-controlsOptional

Reference the id of the menu or submenu that a trigger controls.

aria-activedescendantOptional

Optional alternative to moving DOM focus. Useful when menu items contain inputs.

aria-checkedOptional

Required for menuitemcheckbox or menuitemradio when representing toggled states.

Implementation Checklist

  • Close the menu when focus leaves the menu container unless it moves into a submenu.

  • Trap focus inside an open menu by looping arrow navigation or returning focus to the trigger.

  • Support hover activation but never rely on hover alone—keyboard users must access every command.

  • Place menus adjacent to triggers in DOM order or manage aria-owns/aria-controls carefully.

  • Ensure submenus announce context (e.g., “Font Size submenu”) via aria-label.

Code Examples

Menu Button Pattern

Trigger button toggles aria-expanded and keeps focus inside the menu.

<button
  id="menu-trigger"
  aria-haspopup="menu"
  aria-expanded="false"
  aria-controls="file-menu"
>
  File
</button>

<div id="file-menu" role="menu" aria-labelledby="menu-trigger" hidden>
  <button role="menuitem">New File</button>
  <button role="menuitem">Duplicate</button>
  <button role="menuitem">Move to...</button>
  <button role="menuitem" disabled>Delete</button>
</div>

Menu with Submenu

menuitem opens another role="menu" with ArrowRight.

<div role="menu" aria-label="Text formatting">
  <button role="menuitemcheckbox" aria-checked="true">Bold</button>
  <button role="menuitemcheckbox" aria-checked="false">Italic</button>
  <div role="none" class="submenu-trigger">
    <button
      role="menuitem"
      aria-haspopup="menu"
      aria-controls="font-size-menu"
      aria-expanded="false"
    >
      Font size
    </button>
    <div id="font-size-menu" role="menu" hidden>
      <button role="menuitemradio" aria-checked="false">12px</button>
      <button role="menuitemradio" aria-checked="true">14px</button>
      <button role="menuitemradio" aria-checked="false">16px</button>
    </div>
  </div>
</div>

Best Practices

🧭

Preserve context

Keep menus attached to the element that invoked them so assistive tech describes the relationship.

⌨️

Match native menus

Adopt the same arrow, Escape, and Enter semantics that users expect from operating system menus.

🔁

Return focus

Always return focus to the trigger when the menu closes, even if closed via pointer click.

Common Mistakes

Hiding menu with display:none

Removing the menu from the accessibility tree between openings breaks aria-controls references.

Leave the menu in the DOM and toggle the hidden attribute or use visibility/opacity.

Skipping menu roles

Using a list with no role prevents screen readers from switching to menu interaction mode.

Set role="menu" and apply menuitem roles to children.

Related Roles & Patterns

menubar

Top-level horizontal navigation that owns menus.

Learn more

menuitem

Individual actionable item inside a menu.

Learn more

menuitemcheckbox

Toggleable command inside a menu.

Learn more

menuitemradio

Mutually exclusive command inside a menu.

Learn more