如何使用Tailwind CSS实现带transform/zoom效果的背景图视差滚动
带缩放/位移动效的视差滚动实现方案
background-attachment: fixed 只能实现背景固定的伪视差效果,存在移动端兼容性差、无法自定义位移速率、无法添加缩放动效的问题,要实现你需要的常规视差效果,用「容器裁切+独立背景层+滚动事件计算变换值」的方案即可,不需要引入额外第三方库。
实现逻辑
- 给
.bg-image容器设置相对定位、溢出隐藏,作为视差效果的可视窗口 - 用容器的
::before伪元素承载背景图,设置绝对定位,宽高比容器大20%预留动效余量,避免位移/缩放时露出白边 - 监听页面滚动,计算每个视差容器相对于视口的位置,按比例给背景层设置Y轴位移(位移速率慢于页面滚动速率形成视差错位)和缩放值,实现滚动时的zoom效果
- 加滚动事件节流、GPU加速属性,保证滚动流畅度
完整代码
结构部分
直接使用你现有的HTML结构即可,不需要额外新增DOM节点:
<body> <nav> <ul> <li><a href="#">link</a></li> <li><a href="#">link</a></li> <li><a href="#">link</a></li> <li><a href="#">link</a></li> <li><a href="#">link</a></li> <li><a href="#">link</a></li> </ul> </nav> <div class="bg-image"> <div class="content"></div> </div> <div class="bg-image"> <div class="content"></div> </div> </body>
样式部分
* { margin: 0; padding: 0; box-sizing: border-box; } /* 导航固定在顶层 */ nav { position: fixed; top: 0; width: 100%; z-index: 999; background: rgba(255,255,255,0.9); padding: 1rem 0; } nav ul { display: flex; gap: 2rem; list-style: none; justify-content: center; } nav ul li a { text-decoration: none; color: #222; } /* 视差容器核心样式 */ .bg-image { position: relative; width: 100%; height: 100vh; /* 可按需调整容器高度,JS会自动适配 */ overflow: hidden; display: flex; align-items: center; justify-content: center; } /* 给第二个视差块设置不同背景示例 */ .bg-image:nth-child(3)::before { background-image: url('your-second-bg.jpg'); } /* 背景层用伪元素实现,不额外加DOM */ .bg-image::before { content: ''; position: absolute; top: -10%; left: -10%; width: 120%; height: 120%; /* 替换为你的第一个背景图地址 */ background-image: url('your-first-bg.jpg'); background-size: cover; background-position: center; /* 用CSS变量接收JS计算的变换值 */ transform: translate3d(0, var(--bg-translate-y, 0), 0) scale(var(--bg-scale, 1)); will-change: transform; /* 开启GPU加速,提升滚动流畅度 */ z-index: 0; } /* 内容层置于背景上方 */ .bg-image .content { position: relative; z-index: 1; color: #fff; font-size: 2rem; text-align: center; max-width: 1200px; padding: 0 2rem; }
交互逻辑部分
// 视差参数,可按需调整 const parallaxConfig = { translateYRatio: 0.4, // 背景位移速率比,值越小视差错位感越强 initialScale: 1, // 背景初始缩放值 maxScale: 1.1, // 容器滚动到视口中间时的最大缩放值,实现zoom效果 }; // 节流函数,避免滚动事件触发频率过高导致卡顿 function throttle(func, delay = 16) { let lastTime = 0; return function(...args) { const now = Date.now(); if (now - lastTime >= delay) { func.apply(this, args); lastTime = now; } } } function updateParallax() { const bgContainers = document.querySelectorAll('.bg-image'); const windowHeight = window.innerHeight; bgContainers.forEach(container => { const rect = container.getBoundingClientRect(); const containerTop = rect.top; const containerHeight = rect.height; // 计算容器当前在视口中的位置进度:范围0~1,0代表容器刚从下方进入视口,1代表容器刚完全离开视口顶部 const viewportProgress = (windowHeight - containerTop) / (windowHeight + containerHeight); // 计算Y轴位移:背景移动速度慢于页面滚动速度,形成视差 const translateY = (viewportProgress - 0.5) * containerHeight * parallaxConfig.translateYRatio * -1; // 计算缩放值:容器靠近视口中心时逐渐放大,远离时逐渐回缩 const scale = parallaxConfig.initialScale + (1 - Math.abs(viewportProgress - 0.5) * 2) * (parallaxConfig.maxScale - parallaxConfig.initialScale); // 把计算值通过CSS变量传给背景层 container.style.setProperty('--bg-translate-y', `${translateY}px`); container.style.setProperty('--bg-scale', scale); }) } // 绑定事件 window.addEventListener('scroll', throttle(updateParallax), { passive: true }); window.addEventListener('resize', throttle(updateParallax), { passive: true }); window.addEventListener('load', updateParallax);
参数调整说明
- 如果不需要缩放效果,把
maxScale的值设为和initialScale一致(均为1)即可 - 如果想要更强的视差错位感,把
translateYRatio调小(比如0.2),想要更弱的视差就调大(比如0.6) - 不同视差块需要不同背景图,参照示例里的
:nth-child(3)::before写法单独设置background-image即可 - 容器高度不需要固定为100vh,修改
.bg-image的height属性为任意值,JS逻辑都会自动适配
内容的提问来源于stack exchange,提问作者Dev.malikali
相关产品推荐
相关产品推荐

