Prevent Scroll Chaining With overscroll-behavior
A scrollable list reaches its last item, but the next wheel movement sends the page behind it scrolling. That hand-off is called scroll chaining. overscroll-behavior lets a scroll container prevent it at its boundary.
The hand-off can be useful on an ordinary page. In a chat panel or a separate overlay, keeping the interaction inside the panel can make more sense.
Apply overscroll-behavior to the scrolling element
The rule belongs on the element with scrolling overflow:
<div class="panel" tabindex="0" role="region" aria-label="Scrollable notes">
<div class="panel-content">
<p>Scroll through these notes.</p>
<p>At the end, continued scrolling should stay within the panel.</p>
</div>
</div>
.panel {
max-height: 12rem;
overflow-y: auto;
overscroll-behavior-y: contain;
}
.panel-content {
min-height: 24rem;
}
The content’s minimum height makes this short demonstration overflow. Real content would normally supply the height itself. Put the panel on a page that can also scroll to compare how the two areas interact.
According to the MDN overscroll-behavior reference, contain prevents scrolling from continuing outside the container. The -y longhand restricts this choice to the vertical axis.
The panel remains scrollable. What changes is the boundary behaviour after it reaches the top or bottom.
Compare containment with removing the bounce
For stopping scroll chaining, the main distinction is between preserving normal boundary feedback and suppressing it:
| Value | Scroll chaining | Local overscroll feedback |
|---|---|---|
auto | Uses the browser’s normal behaviour. | Uses the browser’s normal behaviour. |
contain | Prevented. | Normal local effects can remain. |
none | Prevented. | Local overscroll effects are also suppressed. |
The overscroll specification distinguishes local feedback, such as a bounce effect, from actions that affect another scrolling area or navigate the page.
Stopping the page behind a panel from moving does not necessarily require removing the panel’s own boundary feedback. contain is enough for that narrower requirement; none makes an additional design decision.
Actual feedback varies by browser and platform. A device that does not show a bounce cannot demonstrate the visual difference between those values.
A local rule is not a complete background scroll lock
A rule on the panel controls scrolling that reaches its boundary. It does not prevent someone from scrolling an uncovered part of the underlying page.
That distinction matters for overlays. A panel can stop chaining correctly while the page remains scrollable through other interactions.
A real modal also needs appropriate focus and interaction behaviour. The native dialog element supplies modal behaviour when opened with showModal(); overscroll containment is a separate part of the scrolling design.
For an existing modal’s inner scrolling area, the CSS might look like this:
.modal-content {
max-height: 80dvh;
overflow-y: auto;
overscroll-behavior-y: contain;
}
This limits the inner area’s height and contains vertical chaining. It does not turn an arbitrary element into a modal or establish a complete background-scrolling policy by itself.
Limit the axis you intend to control
A horizontal card strip can contain horizontal boundary behaviour while leaving vertical page scrolling to its normal handling:
.carousel {
display: flex;
gap: 1rem;
overflow-x: auto;
overscroll-behavior-x: contain;
}
.carousel > * {
flex: 0 0 80%;
}
Use this with the strip’s existing card elements. The child sizing makes the cards overflow horizontally instead of simply fitting them into the available width.
The axis longhands make that intent explicit. The shorthand accepts one value for both axes, or two values for the horizontal and vertical axes respectively.
A vertical sidebar and a horizontal gallery need not share the same containment rule. Keeping those choices on the individual components makes the interaction easier to reason about.
Browser navigation gestures need consideration too
The boundary-action rules include actions such as navigation, as well as scroll chaining. MDN also documents the relationship with pull-to-refresh behaviour.
Applying containment globally can therefore affect more than a nested panel. Removing a browser gesture from the whole page deserves a specific reason, rather than being a side effect of a copied component rule.
For an independent chat panel, containing vertical chaining is a clear local choice. For a long article with a small sidebar, allowing scrolling to continue into the page may be the more convenient interaction.
Check the boundary even when the content is short
The specification’s scroll-boundary definition treats a scroll container with no overflow in its scrolling direction as already being at the boundary.
That means a panel’s behaviour can matter even when its latest content is too short to need scrolling. Check both a full list and a short one, rather than testing only the overflowing case.
Also distinguish a genuine scroll container from an ordinary wrapper. Setting the property on a parent does not replace setting it on the element that actually owns the scrolling interaction.
Leave room for normal browser behaviour
MDN currently marks the shorthand as having limited availability. Check the specific values and longhands required by the component against the browsers it supports.
Where a declaration is unsupported, the browser keeps its normal boundary behaviour. That can be acceptable for an optional panel improvement, but it should not be the only mechanism a modal relies on.
Before introducing another nested scroll area, consider whether the content can remain part of the main page. Containing the hand-off can improve an independent panel; it cannot make several competing scroll regions into a simple layout.
Filed under CSS on