CSS overscroll-behavior-x Property
This property controls how the browser handles horizontal scrolling when the boundary of a scrollable element is reached.
| auto | The default behavior where scroll chaining and overscroll affordances occur on the horizontal axis. |
| contain | Prevents horizontal scroll chaining to parent elements but allows local overscroll effects like the rubber-band bounce. |
| none | Prevents both horizontal scroll chaining and local overscroll effects or navigation gestures. |
Code Examples
A basic horizontal scroll area that uses contain to prevent the parent page from scrolling when the boundary is hit.
<div style="width: 300px; height: 150px; overflow-x: auto; overscroll-behavior-x: contain; border: 2px solid #333333; white-space: nowrap;">
<div style="display: inline-block; width: 400px; height: 100%; background: #ffcc00;">Scroll horizontally...</div>
<div style="display: inline-block; width: 400px; height: 100%; background: #00ccff;">The parent page won't move.</div>
</div>An advanced horizontal carousel that uses none to disable navigation gestures and includes a script to toggle the behavior.
<div id="carousel" style="width: 100%; overflow-x: scroll; overscroll-behavior-x: none; white-space: nowrap; background: #eeeeee;">
<div style="display: inline-block; width: 80%; height: 200px; background: #7700ee; color: #ffffff;">Panel 1</div>
<div style="display: inline-block; width: 80%; height: 200px; background: #ee0077; color: #ffffff;">Panel 2</div>
</div>
<script>
const box = document.getElementById("carousel");
// Toggle behavior dynamically
box.addEventListener("dblclick", () => {
const current = getComputedStyle(box).overscrollBehaviorX;
box.style.overscrollBehaviorX = current === "none" ? "auto" : "none";
console.log("Behavior updated to: " + box.style.overscrollBehaviorX);
});
</script>Pro Tip
This is the ultimate fix for side-drawers or mobile menus that trigger the browser's "back" button behavior when a user swipes them closed. Set the container to "overscroll-behavior-x: none" to ensure the swipe gesture stays inside your app logic rather than triggering a URL change.
Deep Dive
Think of scroll chaining like a relay race. When you reach the end of a scrollable box, the browser usually passes the "baton" to the parent container, making the whole page move. By setting this property to "contain", you break that relay and keep the scroll focus on the specific element. Using "none" goes a step further by killing the "rubber-band" or bounce effect entirely. This is specific to the X-axis, which is the horizontal plane, making it the perfect tool for carousels or side-scrolling galleries that shouldn't interfere with the rest of the page layout.
Best Practices
Use this property when you have a horizontal component, like a data table or image slider, nested inside a page that also scrolls. It keeps the user locked into your component instead of the whole page jumping when they reach the end of the content. It is most effective for preventing the "swipe-to-navigate" back and forward gestures found in modern desktop and mobile browsers, which can accidentally kick a user out of your application while they are just trying to browse a slider.
Common Pitfalls
A common mistake is applying this to an element that doesn't have an active horizontal scrollbar. If "overflow-x" isn't set to "auto" or "scroll", this property won't have any visible effect. Also, remember that it only targets horizontal movement; if your container scrolls in both directions, you will still see chaining on the vertical axis unless you also define "overscroll-behavior-y" or use the shorthand property.
Accessibility
Disabling standard scroll behavior can sometimes disorient users who rely on browser cues to know they have reached the end of a page. Use "contain" over "none" when possible to maintain the visual "bounce" feedback while still preventing the parent page from moving. Only use "none" if the overscroll effect is actively breaking your user interface or causing layout glitches during heavy interaction.
Dev Data Table: overscroll-behavior-x property
| default | auto |
| animatable | no |
| inherited | no |
| experimental | no |
| year_intro | 2017 |
| year_standard | 2017 |
| js_syntax_1 | element.style.overscrollBehaviorX |
| js_syntax_2 | element.style.setProperty("overscroll-behavior-x", "none") |
| js_note | Target this property to dynamically prevent navigation gestures or bounce effects based on application state. |
| browsers | { "Chrome": 63, "Edge": 79, "Firefox": 59, "Safari": 16, "Opera": 50, "Chrome Android": 63, "Safari on iOS": 16, "Samsung Internet": 8, "Opera Mobile": 46 } |