视差滚动应优先使用 transform: translatey() 而非 position 定位;需基于容器 getboundingclientrect() 计算滚动比例,配合 requestanimationframe 节流;多层位移须统一基准与 transform-origin,并设 transform-style: preserve-3d。

视差滚动里 transform 和 position 别混用
视差滚动本质是让不同元素以不同速度滚动,不是靠“定位”把它们钉在页面某处。很多人一上来就给层加 position: fixed 或 position: sticky,结果发现滚动卡顿、层级错乱、手机上失效——因为这些定位方式会脱离文档流,干扰滚动容器的事件传递和合成层判断。
真正可控且性能友好的做法,是用 transform: translateY() 动态调整每个层的位移量。浏览器对 transform 的动画优化成熟,能进 GPU 合成层;而 top/left 配合 position 触发重排,尤其在滚动中高频更新时掉帧明显。
- 滚动监听里只更新
transform,不碰top/left或margin - 确保各层有
will-change: transform(或至少父容器设contain: paint) - 避免对
body或html直接设overflow: hidden,这会让 iOS Safari 丢掉原生滚动惯性
background-attachment: fixed 看似简单,但兼容性坑多
用 CSS 原生实现最简视差,确实可以靠 background-attachment: fixed,比如给某个 section 设带背景图的固定层。但它在移动端几乎不可靠:iOS Safari 从 15.4 开始才部分支持,Android Chrome 对混合滚动容器(如 overflow-y: scroll 的 div)常直接忽略该声明。
更隐蔽的问题是,它不响应 scroll-behavior: smooth,也不配合 IntersectionObserver 精确触发,一旦页面有动态加载内容,背景位置容易偏移。
立即学习“前端免费学习笔记(深入)”;
- 仅限静态全屏背景场景,且明确要求支持 iOS 16+ / Chrome 95+
- 必须配合
background-size: cover和background-position: center,否则缩放时撕裂 - 别指望它和 JS 控制的其他层保持速度一致——它的“速度”由浏览器渲染管线决定,无法调节系数
用 getBoundingClientRect() 算滚动比例比 scrollTop 更稳
直接用 document.documentElement.scrollTop 或 window.scrollY 做视差位移基准,容易在不同设备、缩放、iframe 嵌套下出偏差。比如 Safari 移动端返回时可能重置 scrollY,或者页面有横向滚动时 scrollTop 不准。
更鲁棒的方式是监听目标容器(比如一个 .parallax-container)的 getBoundingClientRect(),取 top 和 height 推算当前可视比例。这样位移逻辑绑定到具体元素,不依赖全局滚动状态。
- 监听容器而非
window,避免 iframe 或嵌套路由影响 - 用
requestAnimationFrame节流,别在scroll事件里直接算——iOS 上scroll是异步派发的 - 示例关键逻辑:
const rect = container.getBoundingClientRect(); const ratio = (window.innerHeight - rect.top) / (window.innerHeight + rect.height);
多层视差必须分清“移动系数”的参照系
三层视差(前景/中景/背景)不是简单设 0.3x/0.6x/1.0x 就完事。系数大小本身没意义,关键是谁减谁——所有层的位移必须基于同一滚动基准(比如容器顶部进入视口的瞬间为 0%,底部离开为 100%),否则滚动到一半时层与层之间会突兀错位。
另一个常被忽略的点:CSS transform 的原点默认是元素中心,但视差位移通常要以顶部对齐为基准。如果没设 transform-origin: top center,图片或容器边缘会出现意外滑动。
- 统一用容器的
getBoundingClientRect().top计算进度,别混用scrollTop和offsetTop - 每层位移 =
baseOffset * coefficient,其中baseOffset是基准层位移(如背景层设为 0,中景为 -50px,则前景应为 -100px) - 务必给所有视差层加
transform-style: preserve-3d,否则嵌套变换时透视丢失
视差滚动最难调的从来不是“怎么动”,而是“动得同步”。系数差 0.05,滚到底部时可能偏移上百像素——这种误差肉眼难查,只能靠录屏逐帧比对。










