<p>不能只用CSS写死width: 100%因为其无法获取滚动比例,必须用JS实时计算window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)并用transform: scaleX()更新进度条,同时需挂载到position: relative的稳定容器且配齐top/left/width。</p>

为什么不能只用CSS写死 width: 100%
因为 width: 100% 是相对于父容器宽度(或视口),不是滚动比例。顶部进度条要表达“已滚多少 / 总可滚高度”,这个值必须由 JS 实时算出并注入——CSS 本身读不到 window.scrollY 或 document.documentElement.scrollHeight。
position: fixed 必须配齐 top、left、width
漏掉任一属性都会出问题:只写 top: 0,在部分安卓 WebView 下会右偏;没设 width: 100%,进度条可能被父容器 overflow: hidden 截断;不加 left: 0,iOS Safari 地址栏收起时容易跳位。
-
top: 0+left: 0+width: 100%缺一不可 - 别把进度条直接挂
<body>上——React/Vue 动态替换 body 内容时,伪元素或内联样式会被清空 - 推荐挂载到稳定容器如
#app,且该容器需设position: relative(若用::before)
JS 计算滚动百分比的正确公式
错误写法:window.scrollY / document.body.scrollHeight * 100。在标准文档模式下,document.body.scrollHeight 常为 0 或偏小;可滚动距离也不是整个 scrollHeight,而是减去当前视口高度后的剩余空间。
- 正确分母:
document.documentElement.scrollHeight - window.innerHeight - 加上
Math.min(100, ...)防止超 100%(比如页面内容动态加载后 height 变大) - 监听
scroll事件时,建议用requestAnimationFrame节流,避免频繁重排 - 移动端需注意:Safari 地址栏收放会触发
window.innerHeight变化,导致瞬时计算失真,可加防抖
用 transform: scaleX() 比 width 更稳
直接改 width 触发 layout,高频率滚动下易卡顿;transform 属于合成层,性能更好,且 iOS Safari 对它的支持更一致。
立即学习“前端免费学习笔记(深入)”;
- 必须配
transform-origin: left center,否则缩放中心默认是中点,视觉上像从中间“炸开” - JS 更新:用
el.style.transform = `scaleX(${progress / 100})` - 初始状态设
transform: scaleX(0),避免首帧闪动 - 别在父容器上设
transform或perspective,否则fixed元素会变成相对该容器定位
实际最难的不是让条动起来,是让它在各种网络延迟、动态内容插入、iOS 地址栏切换、第三方 UI 框架 z-index 冲突下,依然不跳、不卡、不消失——这些细节往往要真机连测才能暴露。


















