background-attachment: fixed 在 banner 中基本失效,因 ios safari、android chrome v99+ 等主动降级为 scroll;真要视差需用 position: fixed + transform: translatey() 或 perspective + translatez() 二者选一。

background-attachment: fixed 在 Banner 里基本不 work,尤其移动端直接被浏览器静默忽略;真要分层视差,得用 position: fixed + transform: translateY() 或 perspective + translateZ(),二者选一,别混着来。
为什么 background-attachment: fixed 在 Banner 中大概率失效
它不是“写错就失效”,而是浏览器主动降级:iOS Safari 全版本、Android Chrome v99+、所有启用了 transform/filter/opacity 的父容器,都会把 <code>background-attachment: fixed 当作 scroll 处理,连 warning 都不抛。
- 即使写在
上,只要页面用了transform: scale(1)或will-change: transform,它就失效 - 移动端 DevTools 里看 computed 样式,
background-attachment的实际值已经是scroll,不是你漏写了什么 - Banner 容器若靠内容撑高(没设
min-height: 100vh),滚动时背景会“跳帧”或完全不固定
用 position: fixed 实现多层 Banner 视差(JS 驱动)
这是最可控、兼容性最好、调试最直观的方案。每层都是真实 DOM 元素,独立定位、独立位移。
- 所有视差层统一设
position: fixed; top: 0; left: 0; width: 100%; height: 100vh; - 用
z-index显式排序:远层(如云)z-index: 1,中层(建筑)z-index: 10,近层(角色/文字)z-index: 100 - 滚动监听必须包裹
requestAnimationFrame,否则 iOS 卡顿明显 - 只改
transform: translateY(),别碰top或margin-top—— 后者触发 layout,iOS 上一卡一个准 - 动态加
will-change: transform:只在开始滚动后添加,滚动停止 100ms 后移除,避免空转耗资源
示例关键逻辑:
const bgLayer = document.querySelector('.banner-bg');
const midLayer = document.querySelector('.banner-mid');
const fgLayer = document.querySelector('.banner-fg');
<p>function updateParallax() {
const y = window.scrollY;
bgLayer.style.transform = <code>translateY(${y <em> 0.3}px)</em></code>;
midLayer.style.transform = <code>translateY(${y 0.7}px)</code>;
fgLayer.style.transform = <code>translateY(${y * 1.2}px)</code>;
}</p><p>window.addEventListener('scroll', () => {
requestAnimationFrame(updateParallax);
});</p>
用 perspective + translateZ 实现纯 CSS 视差(无 JS)
适合轻量 Banner,对老浏览器支持差但现代 PC 端流畅,且不依赖滚动监听逻辑。
- 外层容器设
perspective: 1px(值越小,视差越强),并加overflow-y: auto或用<section></section>做滚动上下文 - 每层必须设
transform-style: preserve-3d,否则子元素被拍平 - 背景层用
transform: translateZ(-2px) scale(3),中层translateZ(-1px) scale(2),前景层translateZ(0) - scale 补偿公式是
scale(1 + Math.abs(translateZ) / perspective),否则图层会缩得太小 - 所有背景层加
pointer-events: none,否则会挡住下方按钮和链接
移动端必须做的三件事
别指望“写完就能跑”。上线前这三点漏一个,Banner 在手机上就是平铺滚动。
- 用
@supports not (background-attachment: fixed)写兜底样式,降级为background-attachment: scroll+background-size: cover - 检测 UA:Safari/iOS 下直接禁用 JS 视差逻辑,切到
clip-path: inset()+position: sticky的轻量替代方案 - 所有视差层图片必须 WebP + 响应式
sizes+loading="lazy",否则首屏加载卡顿明显
真正难的不是让图层动起来,而是让它们在各种设备、各种滚动速度下都保持节奏一致——位移系数、节流时机、缩放补偿、交互穿透,每个点都得调到像素级稳定。写完别急着合代码,先拿 iPhone 竖屏滚十次,看有没有闪、卡、遮挡、错位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











