如何修复浏览器窗口Resize时页面行为不一致问题?
问题描述
我的网站有三个横向页面,调整浏览器窗口大小时页面行为不一致:
- 调整最左侧页面时,调整过程中仅该页面显示在屏幕上,这正是预期效果。
- 调整中间或最右侧页面时,会短暂显示上一页或下一页;快速调整右侧页面(缩小/放大窗口)时,页面会直接跳转到中间页面。
我希望所有页面都能和左侧页面表现一致,已尝试将Intersection Observer的threshold从0.5改为1,但未解决问题。
解决方案
问题根源在于窗口 resize 时的滚动逻辑冲突,以及 Intersection Observer 在窗口变化时的误触发。可以通过以下几点修复:
- 移除全局平滑滚动:全局
scroll-behavior: smooth会导致resize时滚动动画延迟,和即时定位需求冲突,直接移除该样式。 - 防抖处理resize事件:避免窗口调整过程中频繁触发滚动操作,减少不必要的布局计算。
- 直接控制滚动容器位置:使用
scrollLeft直接设置滚动位置,替代scrollIntoView,避免额外的动画和布局延迟。 - 优化Intersection Observer配置:指定滚动容器为
root,并保持threshold:1,确保只有页面完全进入视口才标记为活跃。
修改后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; box-sizing: border-box; font-family: 'avenir_nextdemi_bold'; } .outer-wrapper { width: 100vh; height: 100vw; transform: rotate(-90deg) translateX(-100vh); transform-origin: top left; position: absolute; scrollbar-width: none; -ms-overflow-style: none; overflow-x: hidden; } ::-webkit-scrollbar { display: none; } .wrapper { display: flex; flex-direction: row; width: 300vw; transform: rotate(90deg) translateY(-100vh); transform-origin: top left; } .slide { width: 100vw; height: 100vh; } .one { background: orange; border: solid 0.5em green; } .two { background: blue; border: solid 0.5em red; } .three { background: yellow; border: solid 0.5em yellow; } .active { border-color: black; } p{ font-size:4rem; color:white; margin-top:5em; text-align:center; } </style> </head> <body> <div class="outer-wrapper"> <div class="wrapper"> <div id="pageleft" class="slide one active"> <p>left page</p> </div> <div id="middle" class="slide two"> <p>middle page</p> </div> <div id="pageright" class="slide three "> <p>right page</p> </div> </div> </div> <script> const slides = document.querySelectorAll('.slide'); const outerWrapper = document.querySelector('.outer-wrapper'); let resizeTimeout; // 配置Intersection Observer const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { slides.forEach(slide => slide.classList.remove('active')); entry.target.classList.add('active'); } }); }, { threshold: 1, root: outerWrapper }); slides.forEach(slide => observer.observe(slide)); // 防抖处理resize事件 window.addEventListener('resize', () => { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(() => { const activeSlide = document.querySelector('.slide.active'); if (!activeSlide) return; // 计算目标滚动位置 const slideIndex = Array.from(slides).indexOf(activeSlide); outerWrapper.scrollLeft = slideIndex * outerWrapper.clientWidth; }, 10); }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者Veli
相关产品推荐
相关产品推荐

