overscroll-behavior:滚到底之后,溢出的滚动去哪
滚动一个聊天框、弹层或下拉列表,滚到它的尽头后还在继续滚——身后的整页也跟着动了。这叫
scroll chaining(滚动链 / 滚动传播)。手机上把页面拉到顶还往下拽会触发下拉刷新、滚到边缘有橡皮筋回弹——这些是浏览器自带的边界默认效果。overscroll-behavior 用一个属性同时管这两件本来相互独立的事。
1 · 同一个属性管的两件事
- 滚动传播(scroll propagation / chaining):嵌套滚动容器滚到自己的尽头后,多余的滚动量是否「漏」给祖先,最终带动整页。
- 边界默认效果(local boundary effect):容器滚到边界时浏览器自带的反馈——移动端的下拉刷新(pull-to-refresh)、橡皮筋回弹(rubber-band)、Chrome 的辉光(glow)。
2 · 动手:嵌套滚动会不会「漏」到外层
下面是一个外层滚动区里嵌着一个内层滚动框。把鼠标放在内层框里向下滚,滚到内层底部后继续滚,观察外层(以及它的 scrollTop 读数)动不动。改内层的 overscroll-behavior 再试一次。
桌面浏览器通常没有橡皮筋回弹,所以这个 demo 只能演示传播这一半;contain 与 none 在桌面看起来一样(都拦住了传播),差别要到触屏 / 触控板 / 移动端才看得出——那里 none 会连内层自己的回弹也去掉。
3 · 四个关键字,正好填满一张 2×2 表
把上面两件事各看成一个开关,合起来共有四种组合,每种都对应一个关键字。先看这张速查表:
| 值 | scroll propagation(传播) | 边界默认效果(回弹) |
|---|---|---|
auto |
✓ | ✓ |
chain |
✓ | ✗ |
contain |
✗ | ✓ |
none |
✗ | ✗ |
四种组合各有一个关键字。auto / contain / none 早已是标准值;第四格 chain(传播 ✓、回弹 ✗)长期空缺——直到 Chrome 150 才补齐:它让滚动照常传播到祖先,但去掉容器自身的边界回弹 / 拉伸。典型用途是把侧边抽屉做成滚动容器——抽屉滑到边不再橡皮筋拉伸,但滚动会接力给身后的页面。下面这张图按上面两个轴摆开,选不同值看落在哪一格(值由上面那个 demo 的下拉框驱动):
支持度:auto / contain / none 三个值各浏览器早已普遍支持;chain 是 Chrome 150(2026) 才新增的第四个值,尚在铺开,使用时应做好降级(不识别 chain 的浏览器会回退到 auto)。
一句话心智模型:contain = 把滚动关在这个容器里,但保留它自己的边界回弹;none = 再把回弹也去掉;chain = 照常向外传播,但不回弹;auto = 默认,放任传播且保留回弹。
4 · 经典用途
- 移动端关掉整页的下拉刷新 / 误触回弹:
html { overscroll-behavior-y: contain }(或none)。 - 弹层 / 抽屉 / 聊天框滚到底不带动背景:容器上
overscroll-behavior: contain。 - 横向 carousel 防止「左滑触发浏览器后退」手势:
overscroll-behavior-x: none(或contain)。 - 轴向写法:简写
overscroll-behavior: <y> <x>,或-x/-y/-block/-inline单独设。
.modal-body {
overflow: auto;
overscroll-behavior: contain;
}
html {
overscroll-behavior-y: contain;
}
.carousel {
overflow-x: auto;
overscroll-behavior-x: none;
}
5 · 边界与细节
- 只对滚动容器(内容溢出且
overflow: auto/scroll,根 viewport 也算)生效;给不滚动的元素设它没有意义。 - 要拦下整页的 pull-to-refresh,必须设在根元素(
html);设在内层不影响整页手势。 - 它管的是「滚动量的去向与边界反馈」,和管「上方内容变高时别跳」的 overflow-anchor 名字像但毫不相关。