视差滚动需用滚动监听+transform而非background-attachment:fixed;推荐getBoundingClientRect()计算偏移、requestAnimationFrame节流、will-change:transform提示合成,并避免与position:sticky共存。
background-attachment: fixed 就能搞定的这个 CSS 属性在移动端基本失效,iOS Safari 会忽略它,安卓部分 WebView 也会降级处理。真正在现代页面中稳定实现视差效果,得靠滚动监听

transform: translateY() 动态偏移,或者用 IntersectionObserver 配合 requestAnimationFrame 控制帧率。
background-attachment: fixed 当主力方案,它只适合简单背景图、且明确不支持移动端的场景transform 而不是 top 或 margin-top 做位移——前者走 GPU 加速,滚动更顺;后者触发布局重排,卡顿明显scroll 事件必须节流,建议用 requestAnimationFrame 包一层,否则快速滚动时容易丢帧getBoundingClientRect() 算视差偏移量最可控比起单纯依赖 window.scrollY,用元素自身相对于视口的位置来算偏移,能更好适配不同屏幕高度、嵌套滚动容器,也方便做「进入视口才启动」的懒加载逻辑。
el.getBoundingClientRect().top,再结合 window.innerHeight 算出当前可视比例(比如 (window.innerHeight - top) / window.innerHeight)100px),就是当前该元素的 translateY 值overflow: hidden 或 transform,getBoundingClientRect() 的结果仍准确,但需确认父级没截断子元素的渲染区域will-change: transform 提前告诉浏览器要动视差元素如果数量多或层级深,不加提示的话,浏览器可能来不及准备合成层,导致首帧闪烁或滚动掉帧。
will-change: transform,但不要滥用——只加在真正需要视差的元素上will-change: all,这会让浏览器过度优化,反而增加内存开销style.willChange = 'transform'
position: sticky 和视差容易打架如果你在视差区域里混用了 position: sticky 标题或导航条,iOS Safari 可能出现定位错乱、粘性失效、甚至整个视差层抖动。这不是 bug,是 WebKit 对复合层叠加的限制。
position: sticky 和 JS 视差逻辑fixed + 手动计算位置),或改用 IntersectionObserver 模拟 sticky 行为视差滚动真正的难点不在“怎么动”,而在“什么时候不动”——滚动惯性、快速回弹、键盘弹出、横竖屏切换,都会让视差偏移量突然跳变。这些边界情况,比写出第一版动效更花时间调试。