不适合做阅读指示器,因其无法自动感知滚动、计算视口占比或响应文档高度变化,必须由 JavaScript 实时计算 scrollY / (document.body.scrollHeight - window.innerHeight) 并更新 value 和 aria-valuenow。

<progress></progress> 不能当阅读指示器用——它不监听滚动、不计算视口占比、不响应文档高度变化。你看到的“阅读进度条”几乎全是 JS 驱动的自定义实现,<progress></progress> 只能被动接收数值,不能自己感知页面滚动。
为什么 <progress></progress> 不适合做阅读指示器
原生 <progress></progress> 是静态数值呈现组件,不是传感器。它没有内置 API 获取文档总高度、滚动位置或可视区域比例。所谓“阅读进度”,本质是 scrollY / (document.body.scrollHeight - window.innerHeight) 的实时计算结果,这必须由 JS 完成。
- 设
<progress value="0.6" max="1"></progress>只会固定显示 60%,不会随你往下滚自动变 - 浏览器不会把
onscroll事件自动绑定到<progress></progress>上 - 即使你手动更新
progress.value,若没同步更新aria-valuenow,屏幕阅读器仍读旧值 - IE 完全不支持,而很多长文页面仍需兼容旧环境
真正可用的阅读进度条怎么写(JS + <progress></progress> 组合)
用 <progress></progress> 当语义化容器,用 JS 实时算并更新它——这是兼顾可访问性与行为控制的合理分工。
- HTML 结构保持简洁:
<progress id="reading-progress" max="100" value="0"></progress> - JS 计算逻辑要防抖:避免每像素滚动都触发重绘,用
requestAnimationFrame或节流(≥ 16ms) - 关键公式必须用整数:
const percent = Math.min(100, Math.round((window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100)) - 更新时必须两步走:
bar.value = percent+bar.setAttribute('aria-valuenow', percent)(旧版 Safari 需要) - 首次渲染前先调一次,避免首屏空白;监听
DOMContentLoaded和resize防止窗口缩放后错位
CSS 自定义填充色和动画的跨浏览器要点
直接给 <progress></progress> 写 background 没用,必须用伪元素,且各浏览器支持不一致。
实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
立即学习“前端免费学习笔记(深入)”;
- 所有浏览器都得先写
appearance: none,否则 WebKit 下伪元素失效 - Chrome/Safari:用
progress::-webkit-progress-bar控轨道,progress::-webkit-progress-value控填充 - Firefox:只认
progress::-moz-progress-bar,不区分轨道/填充,整个条一起染色 - 别用
transition: width——<progress></progress>内部结构不可直接选中;改用transition: transform或靠伪元素自身动画 - 想加渐变?在
::-webkit-progress-value和::-moz-progress-bar上分别写background-image: linear-gradient(...)
容易被忽略的无障碍细节
90% 的阅读进度条代码漏掉这一项:它必须明确告诉辅助技术“这是阅读进度”,而不是“某个未知任务的进度”。
- 不能只靠颜色或长度暗示进度——色盲用户看不到绿色变长
-
aria-label="当前阅读进度"是底线,推荐更具体:aria-label="文章阅读进度,已滚动至 68%" - 如果旁边有同步更新的文本节点(如
<span id="progress-text">68%</span>),记得加aria-labelledby="progress-text" - 不要把百分比塞进
<progress></progress>的 innerHTML,它不解析也不播报——那只是 fallback 内容,仅在完全不支持<progress></progress>时才显示
真正难的不是让进度条动起来,而是让它在滚动卡顿、窗口缩放、字体加载、动态内容插入等真实场景下依然数值准确、更新及时、读屏正确。这些边界情况,往往比主逻辑多花三倍调试时间。


















