页面滚动进度条特效(自研 JS,颜色/高度/位置实时可调)
页面滚动进度条:监听滚动计算阅读进度,顶部/底部位置可选,颜色与高度实时可调,渐变高亮质感,支持页面滚动与任意容器滚动,零依赖。
效果演示(真实可交互)
🎯 拖动下方滚动条:顶部进度条实时反映阅读进度
《前端动效设计原则》节选
滚动进度条是长页面最直观的导航反馈之一,它告诉用户「你读到哪了、还有多少」。本文选自粤喵组件站文档,用于演示滚动进度条的真实效果。
第一条原则:反馈即时。进度条必须与滚动位置严格同步,任何延迟都会让用户失去信任感。实现上只需监听 scroll 事件(或使用被动监听器),计算 scrollTop / (scrollHeight - clientHeight) 即可得到 0-100% 的进度。
第二条原则:视觉克制。进度条默认宽度很细(2-6px),只在靠近时才出现高亮;颜色通常与品牌色一致,也可以做成渐变色增加质感。过度设计的进度条会抢走内容本身的注意力。
第三条原则:性能友好。滚动事件高频触发,应避免在回调里做重计算和 DOM 写操作。推荐做法:回调里只更新 CSS 变量或 transform,把绘制交给浏览器合成器,或使用 requestAnimationFrame 节流。
第四条原则:移动端适配。触屏滚动与桌面滚轮事件行为一致,都是 scroll 事件,因此同一套代码即可覆盖。需要注意 iOS 橡皮筋效果下 scrollTop 可能为负,要做 Math.max(0, ...) 保护。
第五条原则:多容器场景。除了整页滚动,模态框、侧边栏、表格等内部滚动容器同样适用,只需把监听对象换成对应元素即可。本演示就是把「页面」替换成了一个可滚动的 div。
第六条原则:可访问性。进度条是装饰性元素,应添加 aria-hidden="true" 避免被屏幕阅读器朗读;如确需传达进度,请使用带 role="progressbar" 的语义化实现。
演示区用内嵌滚动容器模拟长页面;正式使用时代码不变,只需把监听对象从容器换成
window或document.documentElement。
完整代码
<div class="progress-bar" id="progressBar"></div>
<!-- 长页面内容省略 -->
.progress-bar {
position: fixed;
top: 0;
left: 0;
width: 0%;
height: 5px;
background: linear-gradient(90deg, #6c8cff, #a96cff, #ff8ecf);
box-shadow: 0 0 10px rgba(108, 140, 255, .6);
z-index: 9999;
}
const bar = document.getElementById('progressBar');
function update() {
const doc = document.documentElement;
const max = doc.scrollHeight - doc.clientHeight;
const pct = max > 0 ? doc.scrollTop / max : 0;
bar.style.width = (pct * 100).toFixed(2) + '%';
}
window.addEventListener('scroll', update, { passive: true });
window.addEventListener('resize', update);
update();
核心公式只有一行:进度 = scrollTop / (scrollHeight - clientHeight)。容器内滚动(模态框/侧边栏)时,把 doc 换成 容器元素、window 换成容器即可。
参数说明
| 参数 | 位置 | 说明 |
|---|---|---|
| 颜色 | background: linear-gradient(...) | 渐变三色或品牌单色 |
| 高度 | height: 5px | 2-12px,越细越精致 |
| 位置 | top: 0 / bottom: 0 | 固定顶部或底部,随需求切换 |
| 监听对象 | window / 容器元素 | 整页滚动或局部容器滚动 |
| 更新时机 | scroll + resize | 必须同时监听 resize,否则窗口变化后进度不准 |
兼容性与性能
- 使用
addEventListener('scroll', ..., { passive: true })被动监听,不阻塞滚动线程,即使高频触发也无卡顿 - 每帧只更新一次
width(toFixed(2)避免浮点抖动),浏览器按合成层处理宽度变化,开销可忽略 - 进度计算做了
max > 0保护,内容不满一屏时进度恒为 0,不会出现 NaN 或负值 - 全浏览器兼容(Chrome / Safari / Firefox / Edge / iOS / Android),无需任何 polyfill
常见问题
Q: 和现成的进度条库比有必要自研吗? 完全没必要用库。整个功能只有一行核心公式,第三方库反而引入体积与版本风险;本组件为粤喵自研,含演示共约 30 行代码。
Q: 在 iOS Safari 上进度条会跳吗? iOS 的橡皮筋回弹会让 scrollTop 短暂为负,建议在公式外包裹 Math.max(0, ...);本组件演示中的容器滚动同样适用该保护。
Q: 如何把进度条放进某个区块而不是全屏固定? 把 position: fixed 改为 position: sticky; top: 0,并把滚动监听目标换成该区块的滚动容器即可;块内进度条常用于文章页、文档站。
Q: 可以商用吗? 可以。本组件为粤喵自研原创代码,免费商用无需署名,无任何协议限制。
许可与来源
- 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
- 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
- 首次发布:2026-09-01 · 最近更新:2026-09-01
- 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
- 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理
常见问题
这个组件可以商用吗?
可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。
浏览器兼容性如何?
支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。
怎么修改动画参数?
直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。