为自定义下拉菜单添加完整ARIA支持,需设置触发按钮role="combobox"、aria-haspopup="listbox"、aria-expanded和aria-controls,菜单容器role="listbox",选项role="option"及动态aria-selected,同步键盘交互与ARIA状态更新,并增强辅助信息。

要为自定义下拉菜单添加完整的 ARIA 角色支持,核心是准确映射原生 <select> 的语义和交互行为,让屏幕阅读器能正确识别菜单结构、当前选中项、展开/折叠状态以及键盘导航逻辑。
基础角色与属性:菜单容器与触发按钮
自定义下拉通常由两部分组成:一个可聚焦的触发按钮(如“选择选项”)和一个隐藏/显示的菜单列表。需明确分配角色:
- 触发按钮添加
role="combobox"和aria-haspopup="listbox",表示它控制一个可展开的列表式菜单; - 同时设置
aria-expanded="false"(初始收起)或"true"(默认展开),并动态同步该值; - 用
aria-controls="menu-id"关联触发按钮与菜单容器的 ID,建立明确的控制关系; - 菜单容器使用
role="listbox",并设id="menu-id"与上一步呼应。
选项项语义:每个选项都要有角色和选中状态
菜单中的每一项不是普通 <div> 或 <li>,而应作为可选单位被识别:
- 每个选项元素添加
role="option"; - 用
aria-selected="true"标记当前选中项(仅一个为 true,其余为 false); - 若支持多选,还需在触发按钮上加
aria-multiselectable="true",并在选项中保持aria-selected状态; - 确保所有选项都可键盘聚焦(例如通过
tabindex="-1"),并在展开时将焦点移入第一个选项。
键盘交互与 ARIA 动态更新
ARIA 不仅是静态标记,还需配合真实行为:
- 按下 Enter 或 Space 时切换菜单展开状态,并同步更新
aria-expanded和aria-hidden(菜单容器); - 方向键(↓/↑)在
listbox中移动焦点,同时实时更新各选项的aria-selected; - 选中后,触发按钮的文本应反映当前值,并设置
aria-activedescendant="option-id"指向当前高亮项(尤其在不可见滚动区域时); - 关闭菜单时,焦点应回到触发按钮,并重置
aria-expanded。
辅助信息与无障碍增强
提升理解度和兼容性:
- 为触发按钮提供清晰的可访问名称,用
aria-label或关联<label for="trigger">; - 菜单容器添加
aria-labelledby="trigger-id",让屏幕阅读器读出“XXX 选项列表”; - 禁用状态需同时设
aria-disabled="true"和tabindex="-1",避免键盘误入; - 避免仅用颜色传达状态(如选中高亮),辅以图标、粗体或文字提示。
不复杂但容易忽略的是:ARIA 属性必须随 DOM 状态实时更新,且不能替代原生语义——如果能用 <select> 就优先用;自定义实现时,每一步交互都要有对应的 ARIA 反馈,否则对辅助技术用户而言,它只是个“看不见的黑盒”。










