overscroll-behavior 控制滚动链在边界处是否传播,非防止滚动链;须作用于真实滚动的子元素(如 .modal__content),且需满足高度限制、overflow-y: auto 及内容溢出等条件。

overscroll-behavior 不是“防止滚动链”,而是控制滚动链在边界处是否继续传播——写错位置、没形成有效滚动容器,它就等于没写。
为什么 overscroll-behavior 写在 .modal 上完全无效
因为 .modal 通常是 position: fixed 容器,本身没有 overflow、内容不溢出、浏览器根本不把它识别为滚动容器。属性被静默忽略,连 warning 都不报。
- 真正要加样式的,是它内部那个「实际在滚动」的子元素,比如
.modal__content、.chat-list或.sidebar-menu - 该子元素必须同时满足:
max-height: 70vh(或明确高度)、overflow-y: auto、内容真实溢出(否则没滚动条,属性不触发) - 父级或祖先不能含
transform、will-change、backface-visibility—— 这些在 iOS 15–16 中会破坏滚动链识别
contain 和 none 的区别不是“严不严格”,而是“手感要不要保留”
二者都阻断事件向上传播,但本地反馈完全不同:
-
overscroll-behavior: contain:允许当前元素自身弹性回弹(iOS 橡皮筋、Android glow),只切断冒泡 → 推荐作为弹窗、聊天列表等场景的默认值 -
overscroll-behavior: none:连本地回弹也禁掉,滚到顶/底就硬停 → 仅适合地图画布、全屏轮播等需彻底隔离的场景 - 横向轮播+纵向防穿透?用
overscroll-behavior-y: contain; overscroll-behavior-x: auto
iOS 15 及更早版本必须 JS 补位,但不能乱 preventDefault
CSS 层面再正确,在 iOS 15.x 和部分安卓 WebView 中仍可能穿透。JS 补漏的关键点极易遗漏:
立即学习“前端免费学习笔记(深入)”;
- 先检测支持:
CSS.supports('overscroll-behavior', 'contain'),只对不支持的环境降级 - 监听
touchmove时,必须用e.target.closest('.scrollable')判断是否在允许滚动的区域外滑动 - 绑定事件要加
{ passive: false },否则preventDefault()在 iOS Safari 15+ 被静默忽略 - 不要无差别阻止所有
touchmove,否则遮罩层内可滚动区域(如长列表)会失灵
真正容易被忽略的前提是:overscroll-behavior 不控制“能不能滚动”,只干预“滚到头之后怎么办”。如果内容没溢出、容器没设 overflow、或者滚动链被 transform 断开,再怎么写 none 都只是摆设。


















