应设为 list——表示建议以可聚焦的列表项(role="listbox" + role="option")呈现;both 要求同时支持内联补全和列表,但多数联想组件仅渲染下拉列表,设 both 会误导辅助技术。

aria-autocomplete 应该设为 list 还是 both?
当 input 用于联想搜索(比如输入“北”弹出“北京”“北海道”“北极”),aria-autocomplete 必须明确告诉辅助技术“提示是列表形式呈现”,否则屏幕阅读器可能只读输入内容,不触发建议项播报。
正确值是 list —— 表示建议以可聚焦的列表项(role="listbox" + role="option")呈现;both 要求同时支持内联补全(inline text 插入)和列表,但绝大多数前端联想组件只渲染下拉列表,不自动填充 input 值,设 both 反而误导辅助技术尝试监听文本变化,导致播报错乱或静默。
- 用
list:搭配role="listbox"容器和多个role="option"子项,屏幕阅读器会按列表导航并朗读每个选项 - 不用
none:即使初始无建议,只要设计上支持联想,就应设为list,否则丧失语义 - 不用
inline:这表示输入框内文字会自动补全(如命令行 tab 补全),和下拉联想逻辑不符
为什么加了 aria-autocomplete 还没读出提示?
常见原因是缺少配套的 ARIA 关系链。仅设 aria-autocomplete="list" 不够,必须让屏幕阅读器知道“哪个元素是提示列表”,否则它无法关联 input 和下拉区域。
关键三要素缺一不可:
-
aria-controls属性指向下拉容器的id,例如:<input aria-autocomplete="list" aria-controls="suggestions"> - 下拉容器必须有
role="listbox"和对应id="suggestions" - 每个建议项用
role="option",且带aria-selected="true/false"实时反映焦点状态
漏掉 aria-controls 是最常踩的坑——很多框架(如 React Select、Vue Multiselect)默认不自动绑定这个属性,需手动透传。
动态更新建议列表时,aria-expanded 和 aria-activedescendant 怎么配合?
用户输入触发建议加载后,需要同步更新两个状态属性,否则屏幕阅读器无法感知展开/收起和当前高亮项:
-
aria-expanded="true"在下拉可见时设为true,隐藏时设为false;它控制“是否播报‘已展开’提示” -
aria-activedescendant指向当前被键盘聚焦的option的id(不是value),例如:aria-activedescendant="option-2";它让屏幕阅读器在不移动焦点的情况下播报高亮项
注意:aria-activedescendant 只在 input 本身保持焦点时生效(即用方向键浏览建议,input 始终聚焦)。如果用鼠标点击某个 option 导致焦点移入列表,则需改用 aria-selected + tabindex 管理焦点流。
React/Vue 组件里怎么安全透传这些属性?
多数 UI 库(如 Ant Design、Element Plus)的 AutoComplete 组件内部已封装 ARIA,但默认不开放 aria-controls 或 aria-activedescendant 的手动控制权,容易覆盖或丢失。
实操建议:
- 优先用库自带的
aria-label或aria-labelledby配合说明文字,比强行注入aria-autocomplete更可靠 - 若必须自定义下拉(如用
div + ul实现),务必用useId()(React)或ref(Vue)生成唯一 ID,并严格绑定aria-controls/id/aria-activedescendant - 避免在建议未加载完成时提前设
aria-expanded="true",会导致屏幕阅读器播报空列表
最易被忽略的是异步加载场景:建议数据从 API 返回前,aria-expanded 应保持 false,且不能提前渲染空 listbox 容器——否则会被读作“已展开,含 0 项”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











