移动端 background-attachment: fixed 被 iOS Safari 和 Android Chrome 110+ 主动禁用以省电,降级为 scroll;应使用 @supports 检测并 fallback 到 transform + CSS 自定义属性方案,配合 requestAnimationFrame 节流和 scroll-driven animations 实现稳定视差。

background-attachment: fixed 在移动端根本不动
它在桌面端能跑,但 iOS Safari 和 Android Chrome 110+ 默认禁用 background-attachment: fixed——不是 bug,是浏览器主动降级为 scroll 来省电省内存。结果就是背景跟着内容一起滚,视差感消失。
- 别把它当主力方案,尤其页面要上 App WebView 或微信内嵌页
- 加
transform: translateZ(0)或will-change: transform可骗部分机型启用合成层,但不保稳 - 用
@supports (background-attachment: fixed)包一层,里面写fixed方案;外面 fallback 到transform方案
transform + scrollY 驱动时掉帧卡顿的根因
直接在 scroll 事件里读 window.scrollY 并设 style.transform,会高频触发 layout → paint → composite,在 iOS Safari 上极易掉帧。
- 必须用
requestAnimationFrame节流,且只在回调里读一次scrollY - 把滚动值注入 CSS 自定义属性:
document.documentElement.style.setProperty('--scroll-y', scrollY + 'px') - CSS 侧用
transform: translateY(calc(var(--parallax-speed, 0.3) * var(--scroll-y))),避免 JS 操作 DOM 样式 - 只对真正参与视差的元素加
will-change: transform,乱加会拖慢合成器
scroll-driven animations 中怎么配“慢 30%”
CSS 没有 parallax-speed: 0.3 这种属性。所谓“背景慢”,本质是同一滚动时间线里,animation-range 的覆盖长度和 @keyframes 里 transform 的位移量共同决定的。
- 先定义时间线:
@scroll-timeline main { source: auto; orientation: vertical; } - 背景层:拉长
animation-range: entry 0% cover 120%,同时@keyframes位移写小,比如translateY(-80px) - 前景层:缩窄
animation-range: entry 20% cover 60%,位移写大,比如translateY(-300px) -
cover是归一化进度单位,不是像素;所有位移值必须显式写死,不能靠系数动态算
perspective + translateZ 的层级错位问题
设了 perspective: 1px 和 transform-style: preserve-3d 后,各层用 translateZ() 排列,但容易出现视觉错位或模糊——因为 Z 值太小导致精度溢出,或浏览器对极小透视值处理不一致。
立即学习“前端免费学习笔记(深入)”;
-
perspective值别设1px或0.1px,建议从500px起调,再按需缩小 - 所有参与 3D 的子元素必须加
backface-visibility: hidden,否则可能翻转或闪烁 -
translateZ()的值要用相对单位(如vw、vh)或 JS 动态计算,避免固定像素在不同屏幕失真
实际项目里最容易被忽略的,是滚动时间线的 scroll-offsets 和容器可滚动区域的匹配——哪怕只差 1px,animation-range 就可能截断或偏移,导致某一层视差突然跳变。


















