直接写 --speed: 0.3 没用,因为CSS变量是静态常量,不随滚动实时变化;需将 scrollY 或 deltaY 映射为动态值,配合 @scroll-timeline 或 requestAnimationFrame + 积分公式平滑更新,并通过语义化命名与差异化贝塞尔曲线实现多层视差物理感。

为什么直接写 --speed: 0.3 没用?
CSS 变量本身不响应滚动,--speed: 0.3 这类静态值只是个常量,它不会随用户滚得快慢而变化。真正需要的是把滚动位移(比如 window.scrollY)或滚动速度(deltaY)实时映射成变量值——否则所有图层都以固定系数位移,既没惯性也没阻尼,看着像机械滑块。
用 scroll() + @scroll-timeline 绑定滚动进度
现代方案(Chrome 115+、Safari 16.4+)靠 scroll() 函数把滚动位置转为数值,再喂给 @scroll-timeline 驱动动画。关键不是“设个变量”,而是让变量成为滚动的函数输出:
-
--scroll-progress不是手动赋值,而是由@scroll-timeline parallax-tl { source: selector(#scroller); scroll-offsets: 0%, 100%; }自动产出 - 在动画中用
animation-timeline: parallax-tl,再用calc(var(--scroll-progress) * -200px)控制位移 - 必须配合
cubic-bezier(0.25, 0.46, 0.45, 0.94)模拟自然减速,硬生生线性位移毫无物理感
手写 JS 计算时怎么安全更新 --speed?
若需兼容旧浏览器或精细控制加速度,JS 仍是主力。但别在 scroll 事件里直接改 style.setProperty('--speed', ...) —— 容易丢帧、抖动、触发重排:
- 用
requestAnimationFrame节流,只在下一帧更新变量 - 用积分公式平滑速度:
--speed: calc(var(--speed) * 0.85 + var(--delta-y) * 0.15),其中--delta-y是上一帧与当前帧scrollY差值 - 每次更新前用
clamp()限幅,比如clamp(-150px, calc(var(--scroll-y) * -0.3), 0),防猛甩导致背景撕裂
多图层视差里,变量命名和节奏怎么错开?
物理感不来自单个变量,而来自各层变量的相位差和响应曲线差异。别全叫 --speed,按语义分层命名更可控:
- 远山背景用
--bg-depth-1,系数设* 0.15,加cubic-bezier(0.33, 0.0, 0.67, 0.0)强阻尼 - 中景云层用
--bg-depth-2,系数* 0.45,加cubic-bezier(0.25, 0.46, 0.45, 0.94) - 前景飘叶用
--fg-parallax,系数* 0.8,甚至加轻微rotateZ模拟风力扰动 - 所有变量必须通过
transform: translateY(clamp(...))应用,不能用top或margin-top,否则无法硬件加速
真正难调的不是公式,而是每个图层的阻尼系数、初始偏移、clamp 边界值——这些没法复制粘贴,得在真机上反复拖动、甩动触控板,看哪一帧卡顿、哪一段 overshoot 过度。变量只是管道,手感来自你调参时的手指记忆。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











