纯CSS变量无法独立实现滚动驱动视差,因--scroll-y必须由JS注入,否则calc()计算结果为NaN或0;background-attachment:fixed在iOS 15+ Safari中被完全忽略,Chrome v99+仅支持设于html/body,且父容器含transform/filter/will-change时会静默降级为scroll。

纯 CSS 变量无法独立实现滚动驱动视差——--scroll-y 必须由 JavaScript 注入,否则变量值始终为空或未定义,calc() 计算结果会是 NaN 或 0。
为什么直接用 background-attachment: fixed 不可靠
它在现代浏览器中行为不一致:移动端 Safari(iOS 15+)完全忽略;Chrome v99+ 要求必须设在 html 或 body 上才可能生效;一旦父容器有 transform、filter 或 will-change,就会静默降级为 scroll。这不是 bug,而是规范演进后的主动限制。
scrollY 获取与变量注入的兼容写法
不能只依赖 window.scrollY,IE 和旧版 Safari 不支持。需 fallback 到 document.documentElement.scrollTop 或 document.body.scrollTop:
- 用
Math.max(document.documentElement.scrollTop, document.body.scrollTop)获取真实滚动值 - 在
requestAnimationFrame回调里更新变量,避免节流丢失帧 - 注入到目标元素(或
document.documentElement):el.style.setProperty('--scroll-y', y + 'px') - 别用
/做除法运算(如calc(var(--scroll-y) / 2)),乘小数更安全:calc(var(--scroll-y) * 0.3)
CSS 层级与 transform 升层的关键细节
即使写了 transform: translateY(calc(var(--scroll-y) * 0.3)),若没触发图层提升,动画仍走重绘路径,卡顿明显:
立即学习“前端免费学习笔记(深入)”;
- 必须给该元素加
transform: translateZ(0)(或已有其他transform) - 多个视差层共用同一个
--scroll-y没问题,但每个都要单独升层 - 如果视差层里含可点击内容(如按钮、文字),记得加
pointer-events: none到背景层,并显式设置z-index控制交互层叠顺序
真正难的不是写那几行 calc(),而是滚动事件调度时机、图层是否真正独立、以及移动端 Safari 对 fixed 的彻底放弃——这些不验证,效果上线后大概率只在开发机上动。



















