const el = document.querySelector('.entry-content');
const total = el.offsetHeight - innerHeight;
const passed = Math.min(Math.max(scrollY - el.offsetTop, 0), total);
bar.style.width = (total > 0 ? passed / total * 100 : 100) + '%';

文章读完滚到正文末尾,顶部进度条只走到 62%,继续往下滚过评论区和相关推荐才到 100%,进度和阅读位置完全对不上。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,进度按整个文档的 scrollHeight 算,评论区、推荐位和页脚都算进了分母,正文只占其中一部分。分子用的又是窗口滚动距离,两边口径不一致。

「阅读进度条计算」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。改完隔一天再看一次,当场正常不代表能稳住。

测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

处理上按这个顺序:分母改成文章正文容器的高度,不用 document 的总高度;分子用滚动位置减去正文顶部的偏移,负数取零;文章很短不足一屏时直接显示满格,别算出负值或超过 100%。

改完只确认一件事:滚到正文最后一个段落,进度条正好满格,继续滚到评论区时不再变化。

作者 9823189