如何实现分段滚动:先滚左侧列到底后自动滚右侧列再共同上移?
实现分段式双列滚动逻辑
先调整HTML结构,给关键元素加标识方便后续JS定位:
<section id="intro-section"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </section> <section id="columns-section"> <div class='column-left' id="column-left"> <!-- 填充足够内容才能看到滚动效果 --> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </div> <div class='column-right' id="column-right"> <!-- 填充足够内容才能看到滚动效果 --> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </div> </section> <section class="bottom-section"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </section> <section class="bottom-section"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </section> <section class="bottom-section"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p> </section>
修改CSS,添加状态类控制不同阶段的显示:
#columns-section { position: relative; min-height: 100vh; width: 100%; overflow: hidden; transition: transform 0.5s ease-out; } .column-left { width: 74%; max-height: 100vh; -ms-overflow-style: none; scrollbar-width: none; overflow-y: hidden; float: left; padding-bottom: 2rem; background-color: #fff; position: sticky; top: 0; } .column-left::-webkit-scrollbar { display: none; } .column-left.scrollable { overflow-y: scroll; } .column-left:hover{ scroll-behavior: smooth; } .column-right { width: 26%; max-height: 100vh; overflow-y: hidden; -ms-overflow-style: none; scrollbar-width: none; float: right; padding: 0rem 3rem 6rem; margin: 0 auto; background-color: #00185a; color: #fff; position: sticky; top: 0; } .column-right::-webkit-scrollbar { display: none; } .column-right.scrollable { overflow-y: scroll; } .column-right img { width: 100%; max-width: 396px; } #columns-section.exit { transform: translateY(-100%); } .bottom-section { min-height: 100vh; padding: 2rem; }
核心JS逻辑,监听滚动实现分段控制:
const introSection = document.getElementById('intro-section'); const columnsSection = document.getElementById('columns-section'); const columnLeft = document.getElementById('column-left'); const columnRight = document.getElementById('column-right'); let isLeftScrollable = false; let isLeftAtBottom = false; let isRightScrollable = false; let isRightAtBottom = false; let hasExited = false; window.addEventListener('scroll', () => { if (hasExited) return; // 判断第一个section是否完全滚出视口 const introRect = introSection.getBoundingClientRect(); const introIsOut = introRect.bottom <= 0; // 阶段1:开启左列滚动 if (introIsOut && !isLeftScrollable) { columnLeft.classList.add('scrollable'); isLeftScrollable = true; } // 判断左列是否到底部 if (isLeftScrollable && !isLeftAtBottom) { const leftIsAtBottom = columnLeft.scrollTop + columnLeft.clientHeight >= columnLeft.scrollHeight - 10; if (leftIsAtBottom) { isLeftAtBottom = true; columnLeft.classList.remove('scrollable'); columnRight.classList.add('scrollable'); isRightScrollable = true; } } // 判断右列是否到底部 if (isRightScrollable && !isRightAtBottom) { const rightIsAtBottom = columnRight.scrollTop + columnRight.clientHeight >= columnRight.scrollHeight - 10; if (rightIsAtBottom) { isRightAtBottom = true; columnsSection.classList.add('exit'); hasExited = true; // 动画结束后释放位置,让下方内容正常显示 setTimeout(() => { columnsSection.style.position = 'absolute'; columnsSection.style.top = '0'; }, 500); } } }); // 页面刷新时重置状态 window.addEventListener('load', () => { isLeftScrollable = false; isLeftAtBottom = false; isRightScrollable = false; isRightAtBottom = false; hasExited = false; columnLeft.classList.remove('scrollable'); columnRight.classList.remove('scrollable'); columnsSection.classList.remove('exit'); columnsSection.style.position = 'relative'; });
关键逻辑说明
- 阶段触发:通过
getBoundingClientRect()检测第一个section是否完全离开视口,触发左列滚动。 - 底部检测:用
scrollTop + clientHeight >= scrollHeight判断列内容是否滚到底,减10px是为了兼容浏览器滚动精度误差。 - 状态切换:左列到底后关闭自身滚动、开启右列滚动;右列到底后触发双列移出动画,动画结束后修改布局让下方内容正常显示。
- 刷新重置:页面加载时重置所有状态和样式,避免残留状态影响初始显示。
内容的提问来源于stack exchange,提问作者Joseph Roberts
相关产品推荐
相关产品推荐

