Entry 05

No rubber-band bounce on desktop

Use it on app-like pages with fixed UI, such as a sidebar or a sticky header. On macOS a trackpad scroll stretches the whole page past its edge and drags the fixed UI along.

Open
Open it in its own tab and scroll past the top with a trackpad. The page does not stretch. On a touch device it still does.
Code CSS · 5 lines
html { overscroll-behavior-y: none; }

@media (any-pointer: coarse) {
  html { overscroll-behavior-y: auto; }
}
Why it works, the rules and the credits 3 reasons · 3 rules · credits

Why it works

  1. overscroll-behavior-y: none on the root turns off the bounce.
  2. Touch devices get the default back, because pull to refresh depends on it.
  3. any-pointer checks every input, where pointer checks only the primary one. A device with a touchscreen plus a mouse or stylus keeps pull to refresh. Jhey's example is a foldable.

Rules

  1. Set it on html. The viewport takes its overscroll behavior from the root element.
  2. Use the -y longhand. overscroll-behavior-x: none also turns off swipe to go back.
  3. Give inner scroll containers, such as a sheet, a chat list or a sidebar, overscroll-behavior: contain. They keep their own bounce and stop the page behind them from moving. Never use a touchmove listener with preventDefault() for this.

Credits

Borrowed from: wits, @witsdev on X, 2026-09-30, describing how Vercel gates it behind pointer: fine · Jhey Tompkins, @jh3yy on X, for the any-pointer version · Emil Kowalski, mobile-native skill, for the inner containers

Docs: MDN: overscroll-behavior · MDN: any-pointer