最简滚动视差用 background-attachment: fixed 实现,需容器设明确高度(如100vh)、加 transform: translateZ(0) 修复 iOS 兼容性,避免在 sticky 或 transform 父容器内使用。

用 background-attachment: fixed 实现最简滚动视差
这是兼容性最好、开销最低的方案,适合纯背景图层(如页头 Banner),不需要 JS 干预。
关键点在于:父容器需有明确高度(不能靠内容撑开),且子元素需触发层叠上下文(否则 fixed 在部分 iOS Safari 中失效):
-
background-image必须设在具有height或min-height的块级元素上 - 加
transform: translateZ(0)或will-change: transform强制硬件加速,修复 iOS 滚动卡顿和背景错位 - 避免在
position: sticky或transform父容器内使用 —— 会截断fixed的参照系
.parallax-section {
height: 100vh;
background-image: url('bg.jpg');
background-attachment: fixed;
background-position: center;
background-size: cover;
transform: translateZ(0); /* 关键:iOS 兼容 */
}
用 IntersectionObserver + transform: translateY() 做精准控制
当需要多层视差(前景/中景/背景)、或视差强度随滚动位置线性变化时,CSS fixed 不够用,必须 JS 驱动。但别用 scroll 事件 —— 容易掉帧。
IntersectionObserver 本身不监听滚动,但它能配合 getBoundingClientRect() 算出元素在视口中的相对位置,再驱动 transform:
- 监听目标元素进入视口的时机,用
entry.boundingClientRect.top和window.innerHeight推算滚动比例 - 对不同图层应用不同系数:背景层用
-0.2 * scrollRatio,中景用-0.5 * scrollRatio,前景接近0 - 务必用
requestAnimationFrame批量更新样式,避免强制同步布局(offsetTop等会触发布局抖动)
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const ratio = (window.innerHeight - entry.boundingClientRect.top) / window.innerHeight;
const bg = entry.target.querySelector('.parallax-bg');
bg.style.transform = `translateY(${ -0.3 * ratio * 100 }%)`;
});
}, { threshold: [0, 1] });
<p>observer.observe(document.querySelector('.parallax-section'));</p>
为什么 scroll 事件做视差大概率卡顿
直接监听 window.onscroll 并实时计算 scrollTop 是新手最常写的写法,但实际项目中几乎不可取。
问题不在逻辑,而在浏览器渲染管线:
- 每次
scroll触发都可能引发重排(尤其是读取offsetTop、getBoundingClientRect()时) - 即使只写
transform,若没用requestAnimationFrame节流,JS 执行会挤占主线程,导致滚动丢帧 - 移动端 WebView(如微信内置浏览器)对高频
scroll更敏感,容易出现“跳变”而非平滑视差
替代方案不是“不用 JS”,而是换触发源:IntersectionObserver + raf 组合可把 FPS 稳定在 60,且内存占用低。
移动端适配最容易被忽略的三个点
视差效果在桌面端跑得顺,一到手机就错位、卡死、甚至白屏 —— 大多栽在这几个细节上:
- iOS Safari 对
background-attachment: fixed支持极差,会退化为scroll;必须加transform: translateZ(0)或用 JS 方案兜底 - 安卓部分低端机(尤其 Chrome 80 以下)不支持
IntersectionObserver,需用@supports检测并 fallback 到节流scroll - 视口缩放(双指 pinch-zoom)会破坏
vh单位和getBoundingClientRect()的精度,建议禁用缩放:
复杂点从来不在“怎么做出效果”,而在于“怎么让效果不崩在各种边缘场景里”。滚动视差尤其如此 —— 它天然依赖渲染时序与设备能力,少一个兼容补丁,用户看到的就是撕裂或卡死。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











