为动态加载内容配置屏幕阅读器的问题排查
屏幕阅读器无障碍问题排查与修复
问题概述
表单中输入邮政编码后,下拉城市建议、加载状态(ProgressIcon)、选中地址展示(ShowSelection)均无法被屏幕阅读器自动播报,仅错误提示(CityError)正常工作,已尝试aria-live但未生效。
逐个组件修复方案
1. ProgressIcon 组件
- 问题核心:
aria-live需要作用在始终存在于DOM中的容器上,若组件通过display: none隐藏,屏幕阅读器会忽略其监听;直接给容器加aria-label的可靠性低于显性文本。 - 修复代码:
<div style={{ visibility: showFetchProgress ? 'visible' : 'hidden', opacity: showFetchProgress ? 1 : 0 }} aria-live="assertive" role="status" > <LoadingIcon size={'small'} aria-hidden="true" /> <span className="sr-only">正在获取城市和州信息</span> </div>- 用
visibility替代display: none,保证DOM节点始终存在,让aria-live能捕获状态变化 - 新增仅屏幕阅读器可见的文本(
.sr-only是通用的"仅阅读器可见"样式类),替代aria-label,提升兼容性 - 给加载图标加
aria-hidden="true",避免阅读器识别无意义的图标元素
- 用
2. DropdownOptions(城市建议下拉)
- 问题核心:下拉菜单未与邮编输入框建立关联,且缺少标准的无障碍语义,
aria-live未监听菜单内容的更新通知。 - 修复步骤与代码:
- 先给邮编输入框补充关联属性:
<input type="text" id="zipcode-input" aria-controls="city-suggestions" aria-expanded={showSuggestions} aria-describedby="suggestions-count" /> - 改造下拉菜单容器与选项:
<CitySuggestionWrapper id="city-suggestions" isOpen={showSuggestions} style={{ display: showSuggestions ? 'block' : 'none' }} > <div id="suggestions-count" aria-live="polite" className="sr-only"> {cityStates?.length > 0 ? `${cityStates.length}个城市建议` : ''} </div> <DropdownOptionsWrapper aria-expanded={showSuggestions} error={error} role="listbox" > {cityStates?.map((item: any) => ( <DropdownOptions key={item.city} id={item.city} role="option" aria-selected={selectedCity?.city === item.city} onMouseDown={() => selectItem(item, dispatch)} > <button tabIndex={-1} // 由listbox容器统一管理焦点 onKeyDown={(event) => keyPressSelectItem(event, item)} > {displayCityAddress(item)} </button> </DropdownOptions> ))} </DropdownOptionsWrapper> </CitySuggestionWrapper>
- 用
aria-controls关联输入框与下拉菜单,让阅读器明确两者的控制关系 - 新增
suggestions-count的live区域,主动播报建议数量,让用户感知下拉内容 - 给菜单加
role="listbox"、选项加role="option"和aria-selected,符合WAI-ARIA下拉菜单的标准语义
- 先给邮编输入框补充关联属性:
3. ShowSelection 组件
- 问题核心:组件通过
display: none隐藏时,aria-live无法监听内容更新;缺少明确的状态提示文本。 - 修复代码:
<div aria-live="polite" style={{ visibility: showAddress ? 'visible' : 'hidden', height: showAddress ? 'auto' : 0, overflow: 'hidden' }} > {showAddress ? `已选择地址:${displayCityAddress(selectedCity)}` : ''} </div>- 用
visibility+高度控制显示,保证DOM节点始终存在 - 补充明确的状态前缀文本,让阅读器清晰播报选中结果
- 用
通用无障碍规则
aria-live容器必须始终存在于DOM中,不能用display: none切换显示,否则会被阅读器忽略assertive仅用于紧急信息(如错误提示),普通更新用polite,避免干扰用户操作- 优先使用语义化标签:用
<button>替代<a role="button">,用标准WAI-ARIA角色实现组件语义
内容的提问来源于stack exchange,提问作者kirasam72
相关产品推荐
相关产品推荐

