必须为 role="combobox" 显式设置 aria-haspopup="listbox",否则辅助技术无法识别下拉行为;aria-autocomplete 应优先选用 "list";aria-expanded 和 aria-controls 需随面板状态动态同步;键盘导航需手动实现焦点控制。

role="combobox" 必须配 aria-haspopup="listbox"
只写 role="combobox" 和 aria-autocomplete 是无效的。浏览器不会识别为可展开的自动补全控件,键盘导航(如向下箭头)也不会触发列表显示。必须显式声明 aria-haspopup="listbox",否则 AT(辅助技术)完全忽略下拉行为。
常见错误是照抄文档片段,漏掉这个属性。正确组合是:
<input role="combobox" aria-autocomplete="list" aria-haspopup="listbox" aria-expanded="false" aria-controls="my-listbox"><div role="listbox" id="my-listbox"></div>
aria-autocomplete="list" 不等于 "both" 或 "inline"
aria-autocomplete 的取值直接影响输入框内容是否被自动填充。实际项目中绝大多数自动补全场景应选 "list" —— 它表示仅通过列表项选择来改变值,输入框本身不自动插入文本;而 "both" 要求输入框实时补全字符(类似 Chrome 地址栏),实现复杂且易与用户输入冲突。
-
"list":安全、可控,推荐用于下拉选择类补全 -
"both":需监听input+keydown+ 光标位置,极易导致光标跳脱或覆盖用户输入 -
"inline":仅适用于搜索建议内联插入(如 GitHub 搜索框 @ 用户),不适用于表单字段
aria-expanded 和 aria-controls 必须动态同步
这两个属性不是一次设置就完事的。aria-expanded 必须随下拉面板真实可见状态实时更新(true/false),aria-controls 的值必须精确指向当前关联的 listbox 元素 ID。常见疏漏:
- 用 JS 显示列表但忘记设
aria-expanded="true" - 多个 combobox 复用同一
listboxID,导致语音朗读错乱 - 列表隐藏后未重置
aria-expanded="false",AT 仍认为面板开着
建议在显示/隐藏逻辑中成对操作:
listboxEl.style.display = 'block';
inputEl.setAttribute('aria-expanded', 'true');
inputEl.setAttribute('aria-controls', listboxEl.id);
键盘交互不能只靠 tabindex
仅给 input 设 tabindex="0" 不够。用户按 ↓ 键时,焦点必须能自然落到第一个 option 上,且支持 ↑/↓/Esc/Enter 导航。这意味着:
-
listbox本身不需要tabindex,但每个option必须是role="option"并有唯一id - ↓ 键逻辑必须手动捕获并调用
firstOptionEl.focus(),不能依赖浏览器默认行为 - Enter 选中后,要主动将值写入 input,并设
aria-expanded="false",再把焦点还给 input
没处理好这点,屏幕阅读器用户会卡在输入框里,无法用键盘操作列表。
复杂点在于,所有这些 ARIA 属性和键盘逻辑必须协同工作——少一个,整个自动补全对残障用户就是不可用的。最容易被忽略的是 aria-haspopup 和 aria-expanded 的动态一致性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











