标准 · ARIA

角色 控件

menuitem

将元素标记为菜单或菜单栏内的可操作项。没有对应的 HTML 原生元素——菜单是仅靠 ARIA 实现的构件。仅在构建真正的应用程序式菜单时使用此角色;普通导航列表不应使用 menu/menuitem。

何时使用

仅在 role="menu"role="menubar" 内部使用,且仅当该菜单是应用程序菜单时——即模仿桌面应用文件/编辑/视图菜单栏的那种菜单,具备单 Tab 停靠点、方向键导航和 Esc 关闭功能。

网站的顶部导航不是菜单。应使用带 <ul> 链接列表的 <nav>。将两者混淆是 Web 上最常见的 ARIA 错误——它会让键盘用户陷入方向键导航,而 Tab 键才是更自然的方式;同时它会告诉屏幕阅读器”应用程序菜单”,而内容实际上只是链接。

兄弟角色:menuitemcheckbox(用于可切换的菜单项)和 menuitemradio(用于菜单内的单选项)。

键盘与焦点契约

参照 APG 菜单模式

  • Tab 键进入和退出菜单——进入时焦点落在第一个 menuitem 上。Tab 键不会在各项之间循环。
  • 上/下方向键在各项之间移动焦点(含循环回绕)。
  • 右/左方向键打开子菜单/返回父菜单。
  • Enter 或 Space 激活当前获焦项。
  • Escape 关闭菜单并将焦点返回触发元素。
  • 输入字母可跳转到以该字母开头的下一项(预输入)。

使用漫游 tabindex:只有当前获焦的 menuitem 设置 tabindex="0",其余项设置 tabindex="-1"

常见错误

  • 对网站导航中的普通链接使用 role="menuitem"。会造成键盘陷阱和屏幕阅读器的错误播报。
  • 每个 menuitem 都设置 tabindex="0",导致 Tab 键逐项步进。正确模式是单 Tab 停靠点。
  • 子菜单仅在鼠标悬停时打开,右方向键无法触发。
  • Escape 关闭子菜单后焦点丢失,用户被遗留在菜单之外。
  • 项目缺少无障碍名称,因为图标是唯一内容——请添加 aria-label

示例

<button id="fileBtn" aria-haspopup="menu" aria-expanded="false" aria-controls="fileMenu">
  文件
</button>
<ul id="fileMenu" role="menu" aria-labelledby="fileBtn" hidden>
  <li role="menuitem" tabindex="0">新建</li>
  <li role="menuitem" tabindex="-1">打开</li>
  <li role="menuitem" tabindex="-1" aria-haspopup="menu" aria-expanded="false">
    打开最近
  </li>
  <li role="separator"></li>
  <li role="menuitem" tabindex="-1">保存</li>
</ul>