
要让多级联动表单项(比如“省→市→区”三级下拉)被屏幕阅读器正确、自然地朗读提示,关键不是靠复杂脚本,而是用语义化 HTML 结合 ARIA 属性,让变化可感知、上下文可理解。
用 aria-live 实时播报动态内容变化
当用户选择“省份”后,市级下拉框内容更新,屏幕阅读器默认不会主动读出新选项。此时需在市级下拉容器上添加 aria-live="polite",并配合动态插入提示文案:
<select id="province" aria-label="请选择省份"><option value="">-- 选择省份 --</option> <option value="bj">北京</option></select><p></p><div aria-live="polite" aria-atomic="true" id="city-live-region"></div> <select id="city" aria-label="请选择城市"><option value="">-- 先选择省份 --</option></select>
JS 更新市级选项后,立即写入提示语到 city-live-region:
document.getElementById('city-live-region').textContent =
`已加载 ${provinceName} 的 ${cityOptions.length} 个城市选项`;
这样屏幕阅读器会在空闲时自然朗读该提示,用户立刻知道“有新内容可选”。
为联动项补充 aria-describedby 明确依赖关系
让“市”下拉框明确告诉用户它依赖于“省”的选择,避免孤立操作:
<select id="city" aria-label="请选择城市" aria-describedby="province-label"></select><label id="province-label" class="visually-hidden"> 本选项依赖上方省份的选择,请先选择省份 </label>
配合 CSS 隐藏该 label(仅对屏幕阅读器可见),确保语音流逻辑连贯。
每次联动后重置焦点并声明状态
用户选完省份,自动聚焦到市级下拉框,并用 aria-busy + aria-live 协同表达加载与就绪状态:
- 开始加载市级数据时:给
#city加aria-busy="true",同时city-live-region写入“正在加载城市列表…” - 加载完成时:移除
aria-busy,设置focus()到#city,再更新提示为“城市列表已就绪,共 X 项” - 若无子项(如选了“钓鱼岛”这类无下属城市的区域),显示禁用下拉并用
aria-disabled="true"和提示说明
避免常见无障碍陷阱
- 不用
display: none或visibility: hidden隐藏空下拉项——它们仍会被读出;改用aria-hidden="true"+disabled属性控制可访问性 - 不依赖纯 JS 动态生成
<option></option>后再设aria-label——<option></option>本身不支持 ARIA 标签,应确保文本内容自解释(如“北京市-东城区”比单纯“东城区”更清晰) - 禁用“鼠标悬停触发联动”的交互方式——键盘和触屏用户无法触发,必须基于
change或input事件
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











