overflow: hidden 对 body 无效,因 ios webkit 等不将 body 视为裁剪容器,触控滚动仍透传;应改用 overscroll-behavior: none(作用于 body)或 js 锁定 body 位置并记录 scrolly。

为什么 overflow: hidden 对 body 无效
不是 CSS 写错了,是 iOS WebKit 和部分安卓 WebView(如旧版 UC、QQ)根本不会把 body { overflow: hidden } 当真——视觉上没滚动条,手指一滑,底层页面照样惯性滚动。这是因为 touchmove 事件被透传给了可滚动的祖先(比如 body),而 overflow: hidden 并不拦截默认滚动行为。
常见错误:只加 document.body.style.overflow = 'hidden',真机测试时发现背景页仍在动;更糟的是,某些安卓机型还会因未设 position: relative 导致 fallback 失效。
用 overscroll-behavior 封住穿透(现代首选)
它不重排、不跳顶、不丢 scrollY,直接切断滚动事件向父级的传递,且支持细粒度控制。但注意:它必须设在**实际可滚动的容器上**,不是弹窗 wrapper,而是内部有 overflow-y: auto 的内容区。
- 给弹窗内部可滚动区域(如
.modal-content)加overscroll-behavior: contain - 给
body加overscroll-behavior: none(比overflow: hidden更可靠) - 若只需禁 y 轴穿透(比如保留横向轮播),用
overscroll-behavior-y: none - 兼容性:Chrome 63+、Firefox 59+、Safari 16.4+(即 iOS 16.4+),旧版需降级
iOS 15 及以下必须补 JS + position: fixed 锁 body
仅靠 CSS 不够稳定,尤其 iOS 15 以下。核心思路不是“禁滚动”,而是让 body 物理上失去滚动能力:固定定位后脱离文档流,自然无法被拖拽。
- 打开前记录位置:
const scrollY = window.pageYOffset - 设
document.body.style.position = 'fixed',再设document.body.style.top = `-${scrollY}px` - 关闭时先还原
position和top,再调用window.scrollTo(0, scrollY) - 不要只改
document.body.scrollTop,iOS Safari 中该值常为 0,必须优先读window.pageYOffset
touch-action: none 是兜底还是陷阱?
在弹窗遮罩层(如 .popup-mask)上设 touch-action: none 确实能禁掉所有手势,但它会同时干掉 input、textarea 内部的光标移动和原生滚动,属于“杀敌八百自损一千”。
更稳妥的做法是:只在弹窗根元素上监听 touchmove,且仅当触摸点不在可滚动子元素内才 e.preventDefault():
modalEl.addEventListener('touchmove', e => {
if (!e.target.closest('.modal-content')) e.preventDefault();
});
避免对 document 或 body 直接绑定,否则 textarea 拉不到光标、select 下拉选不了项——这些细节在真机调试时才暴露。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











