给博客加一个阅读进度条
本文目录
阅读进度条看起来只是个装饰,真正做起来却涉及滚动位置、文章高度和移动端地址栏变化。目标很简单:让读者知道还剩多少,同时不打扰阅读。
计算与更新
最直接的做法是监听滚动事件,用已滚动距离除以可滚动总高度。为避免每一帧都触发重排,更新放进 requestAnimationFrame,结果写入 progress 元素的值。文章顶部到正文结束的距离要单独计算,不能直接用整个文档高度。
const bar = document.querySelector('progress');
function update() {
const max = document.documentElement.scrollHeight - innerHeight;
bar.value = Math.min(scrollY / max, 1);
}
addEventListener('scroll', function () { requestAnimationFrame(update); }, { passive: true });
进度条应该像页码,存在时让人安心,不存在时也不影响阅读。
- 滚动监听使用 passive。
- 用 requestAnimationFrame 合并更新。
- 文章高度变化后重新计算。
- 阅读完成后隐藏或淡出。
移动端要特别处理视口高度变化。地址栏收起或展开会改变 innerHeight,如果缓存了初始值,进度就会偏移。每次更新时重新读取,或者在 resize 后重新计算总高度,代价很小。
样式上把进度条固定在顶部,高度控制在两三个像素,颜色与正文形成足够对比即可。不要加闪烁动画,也不要覆盖导航。读完之后让它淡出,读者会把注意力还给内容。一个克制的进度提示,应该在被需要时出现,其余时间保持安静。
还要考虑页面被直接打开在某一段落的情况。刷新后浏览器会恢复滚动位置,进度条应当立即同步,而不是等第一次滚动才更新。文章内跳转、展开的附录和动态插入的图片也会改变总高度,必要时用观察器重新计算。如果站点有顶栏,进度条要和顶栏共用高度,避免遮挡锚点标题。