v153 · css · overflow

overflow: scroll clip

Write overflow: scroll hidden and you get a horizontal scroller with no vertical scrollbar — but you also get a vertical scroll container, silently, and it can still be scrolled by anything that puts focus inside it. Allowing clip to be paired with a scrollable value finally makes "this axis does not scroll" mean what it says.

concepts

  1. What each pair computes to

    Every combination of visible, hidden, clip, scroll and auto, with the value you wrote next to the value the browser kept — and a live test of whether each axis is genuinely scrollable, done by scrolling it.

  2. The scroll you did not ask for

    A horizontal strip built the way everyone builds them, with a control focused inside it. Watch the container scroll on an axis that has no scrollbar, then watch the same thing not happen when the axis is really clipped.

  3. Sticky, per axis

    A sticky header is positioned relative to its nearest scrolling ancestor — one ancestor, for both axes. Once an axis can be clipped instead of hidden, the two axes can answer to different ancestors, which is the layout this change exists to enable.

why it shipped

CSS has long coerced mismatched overflow pairs. Pair visible with anything scrollable and the visible becomes auto; pair clip with anything scrollable and the clip becomes hidden. The second coercion is the problem: hidden means "scrollable, but without a scrollbar", so the axis you meant to switch off is still a scrollport. It has a scroll offset, it responds to scrollTop, and the browser will scroll it to reveal a focused element.

Letting clip survive alongside a scrollable value removes that. The clipped axis stops being a scrollport entirely, which also means position: sticky inside can be constrained by a different ancestor per axis — the layout that was impossible while both axes always shared one scroll container.

the CSS

/* Before: the second value is coerced to hidden, so the block axis is
   still a scroll container — just one without a visible scrollbar. */
.strip { overflow: scroll hidden; }

/* After: the block axis is clipped, not scrolled. Nothing can scroll it,
   including the browser's own scroll-into-view on focus. */
.strip { overflow: scroll clip; }

/* And the coercion that has always applied, for contrast. */
.old  { overflow: visible scroll; }   /* computes to: auto scroll */

enabling it now

Chrome ships this behind the experimental web platform features switch before it reaches stable. Verified on Chrome 150 on this machine: with the flag off, overflow: scroll clip computes to scroll / hidden and the block axis still takes a scroll offset; with it on, it computes to scroll / clip, the axis refuses to scroll, and the sticky header in the third demo pins to the sheet.

chrome://flags/#enable-experimental-web-platform-features

# or, from the command line
google-chrome --enable-experimental-web-platform-features

references