aria-valuenow 和 aria-valuemax 必须成对出现,缺一不可,否则屏幕阅读器会报“进度未知”或静默;二者定义原始数值区间而非百分比,需与 role="progressbar" 同时使用,并同步更新 width 与 ARIA 属性。

aria-valuenow 和 aria-valuemax 必须成对出现,缺一不可
单独写 aria-valuenow="75" 或只设 aria-valuemax="100",屏幕阅读器会读成“进度未知”或直接跳过。这两个属性是 ARIA 进度条的语义基石,浏览器靠它们计算百分比(aria-valuenow ÷ aria-valuemax),并决定是否触发无障碍播报。
常见错误现象:<div role="progressbar" aria-valuenow="75"> —— 缺 aria-valuemin 和 aria-valuemax,JAWS/NVDA 会静默,键盘焦点也无法进入;<div role="progressbar" aria-valuemax="100"> —— 没 aria-valuenow,读屏器报“进度:0%”,但你根本没设初值。
-
aria-valuemin可省略,默认为 0,但显式写上更稳妥(尤其当最小值不是 0 时,比如任务从 10 开始) -
aria-valuenow必须是数字,不能是字符串"75"(虽然多数浏览器会自动转,但某些旧版 VoiceOver 会失败) - 更新时用 JS 直接赋值:
el.setAttribute('aria-valuenow', 82)或el.ariaValueNow = '82'都行,但别用el.setAttribute('aria-valuenow', '82%')
用 div 实现进度条时,width 和 aria-valuenow 必须同步更新
很多开发者只改 style.width,忘了同步 aria-valuenow,结果视觉动了,读屏器还报“20%”。反过来,只更新 ARIA 属性而不动 width,用户看到的还是旧进度——两者是解耦的,必须手动保持一致。
使用场景:文件上传、表单多步提交、后台任务轮询。这类进度常非线性(比如验证快、部署慢),用 <progress> 很难匹配真实耗时,<div role="progressbar"> 更灵活。
立即学习“前端免费学习笔记(深入)”;
- 推荐写法:
el.style.width = (val / max) * 100 + '%'; el.setAttribute('aria-valuenow', val); - 别用
transform: scaleX()控制长度——它不改变盒模型尺寸,读屏器和自动化测试工具无法感知真实进度 - 如果进度值来自服务端小数(如
0.78),统一转整数再设:Math.round(val * 100),避免aria-valuenow="0.78"在部分 Android TalkBack 版本中被截断为 0
aria-valuemin/max 不代表“百分比”,而是数值范围本身
很多人误以为 aria-valuemin="0" 和 aria-valuemax="100" 是在定义“0% 到 100%”,其实不是。aria-valuemin 和 aria-valuemax 定义的是当前任务的**原始数值区间**。比如上传文件总大小 2MB,已传 1.2MB,那应该设 aria-valuemin="0"、aria-valuemax="2097152"、aria-valuenow="1258291",而不是强行换算成百分比。
这样做的好处是避免浮点误差,也方便服务端直接返回原始字节数,前端无需二次转换。读屏器会自动算出比例并播报“已完成约 60%”。
- 若用百分比逻辑,必须确保
aria-valuemax是整数且 ≥aria-valuenow,否则 Safari 会静默忽略 -
aria-valuemin可大于 0,例如分片上传第 3 片到第 8 片,可设min="3"、max="8"、valuenow="5",读作“第 5 片,共 6 片” - 不要把
aria-valuemax设成动态变化的值(如边上传边调整总大小),这会让读屏器反复重读,造成干扰
role="progressbar" 是硬性要求,不是可选项
没写 role="progressbar" 的 <div>,哪怕加了所有 ARIA 属性,也不会被识别为进度组件。键盘用户 Tab 进不去,屏幕阅读器不会主动播报,自动化测试工具(如 axe)直接标为“可访问性失败”。
容易踩的坑:复制 Bootstrap 或某 UI 库代码时删掉了 role 属性,以为 class 名 progress-bar 就够了;或者用 <span> 包裹进度条内容,却没给外层容器加 role。
- 必须加在最外层容器上,不是填充条内部元素
- 如果进度条内含文字(如“上传中… 1.2 MB / 2.0 MB”),文字节点要保留在 DOM 中,不能仅靠
aria-label替代——后者会被读屏器覆盖,且无法被 CSS 选中或用户复制 - 别给
role="progressbar"元素加tabindex="-1",除非你明确禁用键盘交互;默认应允许聚焦,以便读屏器按顺序读取
实际项目里,最常被忽略的是 role="progressbar" 和 aria-valuemin/aria-valuemax 的绑定关系——它们不是装饰,而是可访问性的契约。一旦漏掉,进度信息就只对视力正常用户存在。



















