scroll-timeline 无法实现全局滚动进度条,因其仅定义动画节奏而非实时滚动百分比;必须用 JS 计算 scrollTop/(scrollHeight-clientHeight) 并注入 CSS 变量,再通过 transform: scaleX() 驱动宽度更新。

scroll-timeline 不能用于实现全局页面滚动进度条,因为它不提供可读取的滚动百分比值,也不支持将滚动位置映射为 CSS 变量或 width/scaleX 等样式属性。
scroll-timeline: scroll(root) 为什么不能驱动进度条宽度
-
scroll(root)确实能绑定到文档根滚动容器,但它只定义动画播放的时间节奏(0→1),不是“当前滚动到哪”的状态值 - CSS 中没有类似
scroll-progress()的函数可提取该值,你无法在width、transform或background-position中引用它 - 即使写
@keyframes { from { width: 0% } to { width: 100% } },动画也只会在用户从顶部滚到底部时「播放一次」,无法暂停、回退或实时响应 scrollTop 变化 - 多个元素共用同一
scroll(root)时间线时,起始/结束位置取决于各自 DOM 位置,不是统一按文档总高计算的百分比
--scroll-progress 必须由 JS 计算并注入
- 正确路径是:监听
scroll→ 算出scrollTop / (scrollHeight - clientHeight)→ 写入document.documentElement.style.setProperty('--scroll-progress', value) - 分母必须减去
window.innerHeight,否则滚动到底时宽度可能超 100% - 推荐用
requestAnimationFrame节流,避免 layout thrashing;别用debounce,会导致进度条跳变 - 数值务必过滤:用
Math.min(1, Math.max(0, Number(value))),防止传入null、''或'abc'导致calc(var(--scroll-progress) * 100%)计算失败
宽度更新用 transform: scaleX() 而非 width
-
width触发重排(reflow),频繁更新在低端机上明显卡顿 -
transform: scaleX(var(--scroll-progress))只走合成层,GPU 加速,前提是进度条元素已触发独立合成(加will-change: transform或transform: translateZ(0)) - 初始状态必须设
transform-origin: left,否则缩放中心偏移,看起来像“从中间展开”
移动端 Safari 的两个隐藏坑
-
document.body.scrollTop在 iOS Safari 标准模式下恒为 0,必须用document.documentElement.scrollTop - 若页面启用了
overflow-anchor: auto(默认),有时会抑制scroll事件触发;可显式设html { overflow-anchor: none; }避免
真正可控、可调试、能应对动态内容和多端差异的方案,至今仍是 JS 计算 + CSS 变量 + transform 驱动。原生 scroll-timeline 目前只适合做容器内局部滚动动画,比如卡片淡入、标题高亮,不适合做全局进度指示器。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











