如何实现页面中途修改scroll direction后再恢复原有滚动方向?
竖向→横向→竖向滚动切换效果实现方案
这种效果的核心是通过监听全局竖向滚动偏移量,在指定区段将竖向滚动的位移映射为横向内容的滚动偏移,其余区段走默认竖向滚动逻辑,具体实现步骤如下:
前置准备
页面结构分为3个部分:
- 横向滚动前的普通竖向内容区块
- 横向滚动容器(外层容器 + 内部横向排列的内容容器)
- 横向滚动后的普通竖向内容区块
具体实现
1. 基础样式配置
/* 横向滚动外层容器:高度等于视口高度,预留足够的竖向滚动占位 */ .horizontal-wrapper { height: 100vh; position: relative; overflow: hidden; } /* 内部横向内容容器:宽度等于所有横向内容的总宽度,默认横向排列 */ .horizontal-content { height: 100%; display: flex; position: absolute; top: 0; left: 0; will-change: transform; } /* 单个横向卡片:可自定义宽度,这里以满视口宽度为例 */ .horizontal-item { width: 100vw; height: 100%; flex-shrink: 0; }
2. JS滚动逻辑实现
// 提前计算关键参数 const horizontalWrapper = document.querySelector('.horizontal-wrapper') const horizontalContent = document.querySelector('.horizontal-content') // 横向容器距离页面顶部的距离 const startOffset = horizontalWrapper.offsetTop // 横向内容需要滚动的总长度 = 内容总宽度 - 视口宽度 const horizontalScrollDistance = horizontalContent.scrollWidth - window.innerWidth // 给外层容器设置底部内边距,让页面竖向滚动有足够的空间匹配横向滚动的位移 horizontalWrapper.style.paddingBottom = `${horizontalScrollDistance}px` // 监听滚动事件 window.addEventListener('scroll', () => { const currentScrollY = window.scrollY if (currentScrollY < startOffset) { // 处于前竖向区段,重置横向内容位置 horizontalContent.style.transform = 'translateX(0)' horizontalWrapper.style.position = 'relative' } else if (currentScrollY <= startOffset + horizontalScrollDistance) { // 处于横向滚动区段,固定外层容器,映射竖向滚动位移到横向偏移 horizontalWrapper.style.position = 'fixed' horizontalWrapper.style.top = '0' const horizontalOffset = currentScrollY - startOffset horizontalContent.style.transform = `translateX(-${horizontalOffset}px)` } else { // 处于后竖向区段,固定横向内容到滚动完成的位置,恢复外层容器正常文档流 horizontalWrapper.style.position = 'relative' horizontalContent.style.transform = `translateX(-${horizontalScrollDistance}px)` } })
3. 性能优化方案
如果不需要兼容过旧的浏览器,可以使用CSS Scroll Timeline API实现,不需要监听滚动事件,性能更高:
@keyframes horizontalScroll { from { transform: translateX(0); } to { transform: translateX(calc(-100% + 100vw)); } } .horizontal-content { animation: horizontalScroll linear both; animation-timeline: scroll(root block); /* 调整animation-range匹配横向滚动的触发区间 */ animation-range: entry 100% cover 100%; }
注意:CSS Scroll Timeline API的浏览器兼容性目前有限,生产环境建议配合JS方案做降级处理。
内容的提问来源于stack exchange,提问作者jac
相关产品推荐
相关产品推荐

