role="progressbar"必须配合aria-valuenow、aria-valuemin、aria-valuemax三者缺一不可,仅设role无效;需用aria-label或aria-labelledby提供可访问名称,动态更新时须同步修改aria-valuenow属性,优先使用原生<progress>元素。

role="progressbar" 必须配 aria-valuenow、aria-valuemin、aria-valuemax
仅设 role="progressbar" 不会被识别为有效进度条,屏幕阅读器会忽略它或报“不完整”警告。必须同时声明三个 ARIA 属性,缺一不可:
-
aria-valuenow:当前数值(必需,且必须是数字,不能是字符串如"50"或空值) -
aria-valuemin:最小值(通常为0,不可省略) -
aria-valuemax:最大值(通常为100,不可省略)
例如正确写法:
<div role="progressbar" aria-valuenow="65" aria-valuemin="0" aria-valuemax="100"> 已完成 65% </div>
自定义进度条需用 aria-label 或 aria-labelledby 提供可访问名称
纯 div 没有语义文本,辅助技术无法告诉用户“这是什么的进度”。不能依赖视觉上的文字(如“上传中…”)自动关联。
- 用
aria-label直接提供简明说明:aria-label="文件上传进度" - 或用
aria-labelledby关联外部可见标题(ID 必须存在且唯一):aria-labelledby="upload-title"
错误示例(无名称):
立即学习“前端免费学习笔记(深入)”;
<div role="progressbar" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"> 30% </div>
这会被读作“进度条 30%”,但用户不知道在干什么。
动态更新时必须同步修改 aria-valuenow,且避免频繁重绘
JavaScript 修改进度时,只改 DOM 文本或 CSS 宽度不够——必须显式更新 aria-valuenow 属性值,否则屏幕阅读器不会播报变化。
- 推荐用
element.setAttribute('aria-valuenow', newValue),不要用element.ariaValueNow = ...(非标准,不兼容) - 若每秒更新多次(如 0→100 连续动画),建议限制播报频率(如每 5% 更新一次
aria-valuenow),避免语音打断 - 避免在
requestAnimationFrame中高频 setAttribute,可能触发多余重排
不要用 div + role 替代原生 progress 元素(除非真需要自定义样式/行为)
原生 <progress> 自动携带完整语义和默认键盘支持(如屏幕阅读器朗读“完成度 72%”),且更轻量、兼容性更好。
- 优先用:
<progress value="72" max="100"></progress> - 只有当你必须控制内部结构(如加图标、多段色块)、或需兼容不支持
<progress>的老环境(IE),才用div + role="progressbar" - 注意:部分旧版 JAWS 或 NVDA 对
div[role="progressbar"]的支持弱于原生<progress>,测试时务必实机验证
自定义进度条真正难的不是写对属性,而是让每个状态变更都可感知、可中断、可回溯——尤其是后台任务类进度,用户需要知道“卡在哪了”,而不仅是“走到了哪”。



















