跳到主要内容
技术

给博客加一个阅读进度条

阅读进度条看起来只是个装饰,真正做起来却涉及滚动位置、文章高度和移动端地址栏变化。目标很简单:让读者知道还剩多少,同时不打扰阅读。

计算与更新

最直接的做法是监听滚动事件,用已滚动距离除以可滚动总高度。为避免每一帧都触发重排,更新放进 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 后重新计算总高度,代价很小。

样式上把进度条固定在顶部,高度控制在两三个像素,颜色与正文形成足够对比即可。不要加闪烁动画,也不要覆盖导航。读完之后让它淡出,读者会把注意力还给内容。一个克制的进度提示,应该在被需要时出现,其余时间保持安静。

还要考虑页面被直接打开在某一段落的情况。刷新后浏览器会恢复滚动位置,进度条应当立即同步,而不是等第一次滚动才更新。文章内跳转、展开的附录和动态插入的图片也会改变总高度,必要时用观察器重新计算。如果站点有顶栏,进度条要和顶栏共用高度,避免遮挡锚点标题。

admin

站长 / 作者

记录技术、产品与生活,偶尔写点长文。

发表评论

邮箱不会公开,带 * 的为必填项。

把想法写下来,让它在互联网上生长

这里记录技术、产品与生活。订阅 RSS,更新会第一时间送达。

RSS 订阅