如何实现随垂直滚动触发的水平滚动动画?
这个垂直滚动触发水平滑动的效果确实很吸睛!我来一步步教你用JS和CSS实现,还有实用的优化技巧~
实现核心原理
本质就是把垂直滚动的距离映射为水平元素的位移值:监听页面的垂直滚动事件,计算当前滚动的比例,再把这个比例转换成水平元素的横向偏移量,通过CSS的transform: translateX()来实现滑动。
具体实现步骤(附完整代码)
1. 基础HTML结构
先搭好页面框架,包含需要水平滑动的内容块,以及足够的占位元素让页面能垂直滚动:
<div class="scroll-container"> <!-- 要水平滑动的内容容器 --> <div class="horizontal-content"> <div class="content-card">内容块1</div> <div class="content-card">内容块2</div> <div class="content-card">内容块3</div> <div class="content-card">内容块4</div> <div class="content-card">内容块5</div> </div> <!-- 占位区,让页面能垂直滚动 --> <div class="scroll-spacer"></div> </div>
2. CSS样式配置
设置容器和内容的样式,确保水平内容能横向排列,并且固定在视口中不随垂直滚动位移:
/* 全局重置,可选 */ * { margin: 0; padding: 0; box-sizing: border-box; } .scroll-container { min-height: 200vh; /* 让页面有足够的垂直滚动空间 */ position: relative; } /* 水平内容容器:固定在视口中间 */ .horizontal-content { position: fixed; top: 50%; left: 0; transform: translateY(-50%); display: flex; gap: 2rem; width: max-content; /* 宽度由内部内容决定 */ } /* 单个内容卡片样式 */ .content-card { width: 320px; height: 220px; background: #f5f5f5; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); display: flex; align-items: center; justify-content: center; font-size: 1.4rem; font-weight: 500; } /* 占位区高度,确保页面能滚动 */ .scroll-spacer { height: 100vh; }
3. JavaScript滚动逻辑
监听滚动事件,计算滚动比例并转化为水平位移:
// 获取需要水平滑动的元素 const horizontalContent = document.querySelector('.horizontal-content'); // 计算关键参数:水平内容总宽度、视口宽度、最大可水平位移距离 const totalContentWidth = horizontalContent.offsetWidth; const viewportWidth = window.innerWidth; const maxHorizontalOffset = totalContentWidth - viewportWidth; // 页面总可垂直滚动高度 const maxScrollHeight = document.documentElement.scrollHeight - window.innerHeight; // 监听垂直滚动事件 window.addEventListener('scroll', () => { // 当前垂直滚动距离 const currentScrollY = window.scrollY; // 计算滚动比例(0到1之间,0是顶部,1是底部) const scrollRatio = currentScrollY / maxScrollHeight; // 计算水平位移:比例 * 最大可偏移距离,负值表示向左滑动 const horizontalTranslate = -scrollRatio * maxHorizontalOffset; // 应用位移到元素上 horizontalContent.style.transform = `translateY(-50%) translateX(${horizontalTranslate}px)`; });
优化小技巧
- 防抖处理:滚动事件触发频率极高,加防抖可以减少性能消耗:
// 防抖函数 function debounce(callback, delay = 15) { let timerId; return (...args) => { clearTimeout(timerId); timerId = setTimeout(() => callback.apply(this, args), delay); }; } // 用防抖包装滚动回调 window.addEventListener('scroll', debounce(() => { // 上面的滚动逻辑代码 }));
- 平滑过渡:给
.horizontal-content加transition: transform 0.1s ease,让滑动更丝滑 - 边界限制:可以判断
scrollRatio的范围,确保位移不会超出合理边界,避免内容滑出视口过多
类似实例的核心逻辑
你提到的CodePen类实例,本质都是这个思路的延伸:比如调整滚动比例和水平位移的映射关系(比如滚动一半页面就完成水平滑动),或者给多个元素设置不同的位移速度,做出分层滚动的视觉效果。
内容的提问来源于stack exchange,提问作者outsu
相关产品推荐
相关产品推荐

