← Single-axis scroll containers

v153 · css overflow · grammar + computed values

overflow: scroll clip — combination semantics

How the two-keyword overflow grammar and its per-axis computed-value rules turn “scrollable on one axis, clip on the other” into a single-axis scroll container — and what that does to scroll offsets, scrollbars, and programmatic scrolling on the clipped axis.

syntax

Verbatim from CSS Overflow 3 §3.1:

overflow
  Value:    <'overflow-block'>{1,2}
  Initial:  visible
  Applies to: block containers, flex containers, and grid containers

“The overflow property is a shorthand property that sets the specified values of overflow-x and overflow-y in that order. If the second value is omitted, it is copied from the first.” So overflow: scroll clip means overflow-x: scroll; overflow-y: clip — the first keyword is always the x (inline-in-horizontal-writing) axis, never the “primary” one. The longhands take the same value set: visible | hidden | clip | scroll | auto (plus overlay as a legacy alias of auto).

The value definitions that matter here, verbatim:

Source: CSS Overflow 3 §3.1 (quoted verbatim 2026-07-29)

computed-value rules (what each axis becomes)

The classification that drives everything else — verbatim from the same section:

“The scroll, auto, and hidden values are known as the scrollable values of overflow. They cause the box to be a scroll container and the affected axis to be a scrollable axis. […] The visible and clip values are known as the non-scrollable values. However, if the other axis specifies a scrollable value, a specified value of visible computes to auto, enabling scrolling in its axis. If neither axis computes to a scrollable value, the box is not a scroll container. If only one axis computes to a scrollable value (i.e. the other axis is clip), the box is a single-axis scroll container.”

Declared (x / y)Computed resultScroll container type
scroll / clipunchangedsingle-axis (x)
auto / clipunchangedsingle-axis (x) — no scrollbar until there is x-overflow
clip / scrollunchangedsingle-axis (y)
scroll / hiddenunchangeddual-axis — y is still scrollable programmatically
scroll / visiblevisibleautodual-axis
clip / visibleunchanged (no scrollable value)not a scroll container

The spec’s parenthetical — “i.e. the other axis is clip” — is the whole point: clip is the only non-scrollable value that does not compute away when paired with a scrollable value. hidden cannot produce a single-axis container because it is itself scrollable.

Source: CSS Overflow 3 §3.1 (quoted verbatim 2026-07-29)

the disabled axis: offsets, scrollbars, programmatic scrolling

BehaviorContract
Scroll offset on the clipped axisAlways 0scrollTop/scrollLeft read 0 and programmatic scrolls (scrollTo(), scrollBy(), offset assignment) on that axis do not change it
Scroll metricsscrollWidth/scrollHeight still measure the full overflowing content — clipping does not shrink the measurement
User scrollingNone on the clipped axis: no scrollbar, no wheel/touch/keyboard scrolling — “forbids scrolling entirely, through any mechanism”
scrollIntoView()Scrolls only the scrollable axis of a single-axis container
Dynamic change to clipSwitching an axis from a scrollable value to clip clamps that axis back to offset 0 and repaints
Formatting contextclip alone does not establish one (unlike hidden); a box that is a scroll container (the other axis) still establishes an independent formatting context
Source: WPT single-axis-scroll-apis-programmatic.html; single-axis-overflow-scroll-to-clip.html (assert quoted on the overview); CSS Overflow 3 — clip; CSSOM View — scrollTo()

error and edge behavior

Source: CSS Overflow 3 — overflow grammar; runtime_enabled_features.json5 (snap flag record, 2026-07-29)

examples

/* x-scrollable, y-disabled: a single-axis (x) scroll container */
.rail {
  overflow: scroll clip;   /* = overflow-x: scroll; overflow-y: clip */
}

/* equivalent longhands, scrollbar only when x-overflow exists */
.rail-lazy {
  overflow-x: auto;
  overflow-y: clip;
}

/* NOT equivalent — hidden keeps y programmatically scrollable,
   so this stays a dual-axis scroll container */
.rail-broken {
  overflow-x: auto;
  overflow-y: hidden;
}
// The disabled axis holds no offset:
const rail = document.querySelector('.rail');
rail.scrollTo({ top: 100, left: 40 });
console.log(rail.scrollTop);  // 0 — the y axis is clipped, not scrollable
console.log(rail.scrollLeft); // 40 — the x axis scrolls
Source: semantics per CSS Overflow 3 §3.1 and WPT programmatic-API assertions

compatibility

Same interim status as the overview table (flag still experimental at trunk — see the overview ship-status note). BCD’s multiple_keywords key (Chrome 68 / Firefox 61 / Safari 13.1) records only the two-keyword syntax, not single-axis behavior.

Browseroverflow: scroll clip → single-axis scroll container
ChromeEnabled by default 153 (per the listing); flag experimental at trunk
EdgeNot separately reported
FirefoxUnknown — Mozilla #1418 open, no signal
SafariUnknown — WebKit #680 open, no signal

security and privacy

No new exposure: a grammar/computed-value change with no I/O. The one authoring hazard is that clip disables scrolling through any mechanism on that axis — including assistive-technology and keyboard scrolling — so content must never depend on being reachable by scrolling the clipped axis.