iOS 11 iPad端设置body overflow:hidden仍可滚动问题求助
我之前也遇到过一模一样的iOS Safari滚动坑!模拟器里好好的,一到真实iPad上就失效,这其实是iOS Safari的弹性滚动(overscroll bounce)特性在搞鬼,单纯给body加样式有时候压不住它。下面是我亲测有效的解决方案:
1. 同时给html和body设置样式
iOS有时候会把html元素当成滚动容器,只设置body没用,得两个一起处理:
const htmlEl = document.documentElement; const bodyEl = document.body; // 触发全屏时执行 htmlEl.style.overflow = 'hidden'; htmlEl.style.position = 'fixed'; htmlEl.style.height = '100%'; bodyEl.style.overflow = 'hidden'; bodyEl.style.position = 'fixed'; bodyEl.style.height = '100%';
2. 保存并恢复滚动位置(避免跳顶)
设置position:fixed会让页面直接跳到顶部,体验很差,所以要提前存好滚动位置,退出全屏时还原:
// 进入全屏前先记录当前滚动位置 const currentScrollTop = window.pageYOffset || htmlEl.scrollTop; // 设置样式后,把body定位到当前滚动位置 bodyEl.style.top = `-${currentScrollTop}px`; htmlEl.style.top = `-${currentScrollTop}px`; // 退出全屏时恢复原样 htmlEl.style.overflow = ''; htmlEl.style.position = ''; htmlEl.style.height = ''; htmlEl.style.top = ''; bodyEl.style.overflow = ''; bodyEl.style.position = ''; bodyEl.style.height = ''; bodyEl.style.top = ''; window.scrollTo(0, currentScrollTop);
3. 拦截触摸事件(终极方案)
如果上面的方法还没完全解决,那就在你的全屏div上拦截touchmove事件,阻止默认的滚动行为:
const fullscreenDiv = document.getElementById('你的全屏divID'); // 完全阻止div外的滚动(如果div内部不需要滚动) fullscreenDiv.addEventListener('touchmove', (e) => { e.preventDefault(); }, { passive: false }); // passive必须设为false,否则preventDefault可能不生效
如果你的全屏div内部需要滚动,那就得判断滚动边界,只在滚到顶/底时阻止:
fullscreenDiv.addEventListener('touchmove', (e) => { const isScrolledToTop = fullscreenDiv.scrollTop === 0; const isScrolledToBottom = fullscreenDiv.scrollHeight - fullscreenDiv.scrollTop === fullscreenDiv.clientHeight; // 向上滑到顶,或者向下滑到底时,阻止默认行为 if ((e.touches[0].clientY > e.changedTouches[0].clientY && isScrolledToTop) || (e.touches[0].clientY < e.changedTouches[0].clientY && isScrolledToBottom)) { e.preventDefault(); } }, { passive: false });
把这几步组合起来,基本就能搞定真实iPad上的滚动问题了——iOS Safari的滚动机制确实比桌面浏览器矫情得多,得多加几层防护才行。
内容的提问来源于stack exchange,提问作者Gustavo
相关产品推荐
相关产品推荐

