HTML role 的一些知识

role 里的内容是自己写的,还是有一些范围?

非常好的问题!✅

role 属性的值不是随便写的,它必须是 WAI-ARIA 规范中定义的合法角色(roles)之一。浏览器和辅助技术(如屏幕阅读器)只识别这些预定义的标准角色,自定义的值会被忽略或报 warning


role 的取值范围:来自 ARIA 规范

ARIA 定义了一套有限且标准化的角色列表,分为几大类:

1. Landmark Roles(地标角色,用于页面结构)

  • banner
  • main
  • navigation
  • contentinfo
  • search
  • complementary
  • form
  • region

2. Widget Roles(交互组件)

  • button
  • checkbox
  • radio
  • slider
  • tab, tabpanel, tablist
  • menu, menuitem, menuitemcheckbox, menuitemradio
  • combobox
  • dialog
  • tooltip
  • progressbar
  • switch

3. Document Structure Roles(文档结构)

  • article
  • heading
  • list, listitem
  • table, row, cell, columnheader
  • figure
  • group
  • separator

4. Live Region Roles(动态更新区域)

  • alert
  • status
  • log
  • marquee

5. Abstract Roles(抽象角色,不能直接使用

  • command, composite, input 等 —— 这些是其他角色的父类,禁止在 HTML 中直接写

📚 完整官方列表:

WAI-ARIA 1.2 Roles


❌ 错误示例:自定义 role

<div role="my-custom-button">Click</div>  // ❌ 无效!会被忽略
<div role="nested-menu-item">Item</div>   // ❌ 不是标准角色

这些写法:
- 不会报错(HTML 宽容)
- 但屏幕阅读器无法理解,无障碍语义丢失
- 浏览器控制台可能在 Lighthouse 或 axe 等 a11y 工具中报 warning


✅ 正确做法:使用标准角色

// ✅ 正确:使用标准 menuitem
<div role="menuitem" tabIndex={0}>Save</div>

// ✅ 正确:按钮
<div role="button" tabIndex={0}>Submit</div>

// ✅ 正确:菜单容器
<div role="menu"> ... </div>

🔧 如何选择合适的 role?

原则:模仿原生 HTML 元素的行为和结构

| 你想模拟的元素 | 推荐 role |
|----------------|----------|
| <button> | role="button" |
| <ul> / <ol> | role="list"(但通常直接用 <ul> 更好) |
| <li> | role="listitem" |
| 下拉菜单 | role="menu" + role="menuitem" |
| Tabs | role="tablist", role="tab", role="tabpanel" |
| 弹窗 | role="dialog" |

💡 提示:优先使用语义化 HTML 元素(如 <button><nav>,它们自带 role 和行为。只有在必须用 <div>/<span> 时,才手动加 role


⚠️ 注意:role 要配合其他 ARIA 属性

例如:

<div
  role="menuitem"
  aria-disabled={true}
  tabIndex={-1}
>
  Save
</div>
  • role="menuitem" 告诉“这是菜单项”
  • aria-disabled 表示状态
  • tabIndex 控制是否可聚焦

三者配合才能实现完整无障碍体验。


✅ 总结

  • role 的值必须来自 ARIA 标准列表,不能自定义。
  • 使用标准 role 才能让屏幕阅读器正确理解你的组件。
  • 开发时可参考:ARIA Roles - MDN
  • 如果不确定,优先用原生 HTML 元素(如 <button>),它们更可靠。

你之前的 data-role="nested-menu-item" 可以保留用于测试或调试,但 不要用它代替 role;而 role 应写成标准值,比如 role="menuitem"