← Chrome 153 reference

v153 · css · scrolling · shipped

scroll-axis-lock

Limited availability

  • Chrome · 153 (milestone listing)
  • Edge · not separately reported (Chromium-based)
  • Firefox · no signal
  • Safari · no signal

Not on the Baseline register: the ChromeStatus API record marks the Web Feature ID as “Missing feature”, a webstatus.dev query returns zero matches, and there is no BCD entry (all verified 2026-07-29). Vendor positions on the Intent to Prototype and Ship are “No signal” for both Gecko (mozilla/standards-positions #1435, open at fetch time) and WebKit (WebKit/standards-positions #698).

The scroll-axis-lock CSS property lets an author instruct the browser not to constrain a user's scrolling gesture to a single axis. Set scroll-axis-lock: none on a scroll container and diagonal panning follows the exact vector of the user's touch, trackpad, or wheel input from the very start of the gesture — the behavior 2D interfaces such as maps, diagrams, and infinite canvases need from native scrollers.

Specification in flight — verify before depending on fine print

The milestone=153 listing files this feature as “Enabled by default” (the listing is authoritative for gendn), and the Intent to Prototype and Ship states “Will ship enabled for all users”. Two stability caveats remain on the record as of 2026-07-29:

at a glance

What it isA CSS property, scroll-axis-lock, that controls whether the browser may “lock” (rail) a user's scrolling gesture to one axis on an element — auto keeps the default heuristic, none opts the element out
Grammarauto | none — initial auto, not inherited, animation type discrete
Applies toAll elements per the PR's propdef; the CSSWG resolution phrases it as scroll containers — the lock only has an observable effect on elements that can actually scroll (see context)
Milestone listingChrome 153 — Enabled by default (listing, verified 2026-07-29)
Chromium implementationProperty registered in css_properties.json5 (keywords auto/none, default auto) behind runtime flag ScrollAxisLock (tracking bug crbug.com/479472367)
Spec statuscsswg-drafts PR #14152 open, targeting CSS Overflow Module Level 5; TAG review pending
WPTcss/css-overflow/scroll-axis-lock.html — 2/2 subtests passing in the latest Chrome (experimental) run on wpt.fyi (fetched 2026-07-29)
ChromeStatus5908461532610560 — scroll-axis-lock (Blink component Blink>Scroll)
Source: chromestatus.com/feature/5908461532610560; csswg-drafts PR #14152; explainer

why it exists

When a scroll gesture starts with significantly more movement in one axis than the other, browsers “lock” the gesture to the dominant axis and zero out the perpendicular deltas — a heuristic that stops accidental sideways drift while reading vertically-scrolling content. For interfaces that must pan freely in two dimensions, that same heuristic is a bug: the user has to start every gesture at a careful angle, or restart it once locking kicks in.

Until now the only escape was to bypass native scrolling entirely: set touch-action: none, track touch or wheel deltas in JavaScript, and apply them via transforms or scripted scrollTop/scrollLeft updates. That costs main-thread input latency and jank, re-implements gesture state by hand, and interacts badly with scroll-dependent platform features such as scroll events, scroll snapping, IntersectionObserver, and scroll-driven animations. scroll-axis-lock: none keeps native scrolling — on the compositor — and just disables the locking heuristic.

Source: explainer — introduction; explainer — current workarounds; csswg-drafts #13207 (initial proposal)

how axis locking works (the behavior being controlled)

The specification text (PR #14152) describes the heuristic directly: when handling a scroll resulting from a user's gesture, user agents often lock the resulting scroll to one axis — zeroing out the deltas in the perpendicular axis. The PR's own example: a drag that would scroll an element 500px vertically and 3px horizontally is interpreted as an intended vertical scroll; the UA ignores the 3px delta and all further x-axis deltas for the remainder of the gesture. The lock is therefore gesture-scoped: it is decided at the start of a gesture and persists until that gesture ends.

Axis locking applies across input modalities — touchscreen drags, trackpad pans, and mouse-wheel scrolls — which is exactly why the explainer rejected overloading touch-action (that property filters whether the browser intercepts a touchscreen gesture at all, and has no effect on wheel or trackpad input). The WPT test exercises both touch and wheel paths: in each, a steep 2px-horizontal / 150px-vertical scroll on a scroll-axis-lock: none container must not rail — scrollLeft must land within tolerance of the sent delta rather than being zeroed.

Source: PR #14152 — Scroll Axis Locking section text; explainer — why not touch-action; WPT scroll-axis-lock.html (touch + wheel subtests)

syntax

Formal definition, verbatim from csswg-drafts PR #14152 (targeting CSS Overflow Module Level 5):

Name: scroll-axis-lock
Value: auto | none
Initial: auto
Applies to: all elements
Inherited: no
Computed value: specified value
Animation Type: discrete
Canonical Order: per grammar

A declaration is a single keyword:

scroll-axis-lock: auto;  /* default: UA may rail gestures to one axis */
scroll-axis-lock: none;  /* UA must not rail gestures on this element */

Chromium's registration matches: keywords: ["auto", "none"], default_value: "auto", field_template: "keyword", typedom_types: ["Keyword"], gated by runtime_flag: "ScrollAxisLock" in css_properties.json5. The CSSWG resolution that adopted the property reads: “RESOLVED: scroll-axis-lock:auto|none, applies to scroll containers, not inherited, UNLESS smfr objects” (csswg-drafts #13207, 2026-01-28) — no objection from smfr is on record in the issue, and the PR propdef above is the resulting text.

Source: PR #14152 propdef (verbatim); CSSWG resolution; css_properties.json5

values

ValueContract and effect
auto“The user agent may lock scrolls on the element to one axis.” (PR #14152, verbatim) — default behavior: the UA's axis-locking heuristic applies to gestures on the element. Existing pages behave as they always have.
none“The user agent must not lock scrolls on the element to one axis.” (PR #14152, verbatim) — the gesture's diagonal vector is honored from the first input event: both axes scroll simultaneously, no railing, for the whole gesture.

The property takes exactly one keyword; there are no per-axis variants (the explainer's scope is an all-or-nothing opt-out, not a per-axis lock control). none on a container that only overflows in one direction has no practical effect — there is no perpendicular content to drift into, so the browser cannot scroll that way regardless.

Source: PR #14152 — value definitions; explainer — accessibility considerations (unidirectional containers)

context: where the property applies

Source: PR #14152 propdef; CSSWG resolution; explainer — considered alternatives

behavior: what each value produces

Scenarioauto (default)none
Gesture starts steeply vertical (500px y, 3px x) on a 2D-scrollable containerUA may zero the 3px x-delta and all further x-deltas for the rest of the gesture — the scroll is railed to yBoth deltas applied from the first event; the scroll follows the true diagonal vector
User breaks out of the lock mid-gesture (moves far enough along the other axis)UA-defined; the spec text does not define the breakout threshold — the heuristic is intentionally UA territoryNo lock exists, so there is nothing to break out of
Wheel scroll with a small x component (trackpad two-finger pan)May rail to the dominant axis (wheel path is railed the same way — the WPT wheel subtest exists to prove none disables it)Wheel deltas applied as sent — the test asserts the observed wheel event's deltaX matches the sent delta
Programmatic scrolling (scrollTo(), scrollTop = …, scroll-snap)Unaffected either way — the property governs locking of user gesture scrolls; nothing in the sources restricts script-driven scrolls

The heuristic itself (angle thresholds, breakout distance) remains UA-defined — the property is an opt-out switch, not a parameterization of the heuristic. The spec text defines only what none forbids and what auto permits.

Source: PR #14152 — Scroll Axis Locking section + value definitions; WPT assertions

invalid input and edge behavior

SituationBehavior
Unrecognized value (e.g. scroll-axis-lock: both) or wrong token countThe declaration is invalid and dropped at parse time — standard CSS error handling (CSS Syntax § invalid at computed-value time); the computed value falls back to whatever the cascade otherwise produces (auto by default). No exception, no console error contract.
Global keywords (inherit, initial, unset, …)Accepted as for every CSS property; inherit copies the parent's computed value even though the property is not inherited by default.
none on a non-scrollable or single-axis-overflowing elementNo observable effect — there is no perpendicular scroll to unlock (see values).
Unsupported browser (property unknown)The declaration is ignored entirely; behavior stays at the UA default (auto-equivalent). Guard with @supports if the unlocked experience is load-bearing (see examples).
Changing the property mid-gestureNot specified — neither the PR text nor the explainer defines when during a gesture a change takes effect (recorded as an open question in the critique).
Source: CSS Syntax Level 3 — invalid at computed-value time; explainer — proposed solution

lifecycle: when the decision is made

  1. Style resolution — the property computes to the specified keyword per element (discrete animation type: it flips, it does not interpolate).
  2. Gesture start — on the first scroll-causing input of a user gesture, the UA's scrolling engine decides whether to lock, per the element's computed value: auto lets the heuristic run; none skips it.
  3. During the gesture — under auto, a taken lock zeroes perpendicular deltas for the remainder of the gesture (the PR's example is explicit that the lock persists for the whole gesture). Under none, every delta is applied as input.
  4. Gesture end — any lock lapses with the gesture; the next gesture re-evaluates from scratch. No state persists between gestures, and there is nothing to clean up — the property is idempotent style input, not a subscription.
Source: PR #14152 — Scroll Axis Locking section (gesture-scoped lock, verbatim example)

examples

A 2D map viewport that pans diagonally from the first touch (the explainer's canonical example):

.map-viewport {
  width: 100vw;
  height: 100vh;
  overflow: auto;
  /* Diagonal panning works immediately on touch, trackpad, and wheel */
  scroll-axis-lock: none;
}
.map-content {
  width: 5000px;
  height: 5000px;
}

A swipe-to-dismiss card that follows the finger in 2D instead of snapping to a vertical track:

.dismissable-card {
  overflow: auto;
  scroll-axis-lock: none;
  /* translate the card with the gesture; dismiss past a threshold */
}

Progressive enhancement — apply the unlock only where it is understood, and keep a deliberate choice elsewhere:

@supports (scroll-axis-lock: none) {
  .pan-canvas { scroll-axis-lock: none; }
}

The Chrome Platform Showcase entry for this feature has no live demo route yet (route HEAD-checked 404, 2026-07-29); a meaningful demo also needs real gesture input, which a headless embed cannot drive. When a demo lands it will appear at that URL.

Source: explainer — proposed solution (map example, verbatim pattern); explainer — use cases (swipe-to-dismiss); chrome-platform-showcase (404 at fetch time)

accessibility considerations

Axis locking exists for users: people who find it difficult to swipe in a straight line rely on it to keep unidirectional feeds and articles from drifting sideways. The explainer's mitigations are built into the design:

Authors should still treat none as a deliberate UX choice: on content that is primarily read along one axis, disabling the lock makes accidental diagonal drift more likely for exactly the users the heuristic protects.

Source: explainer — accessibility considerations

web platform tests

The feature has upstream coverage: css/css-overflow/scroll-axis-lock.html, with two promise_test subtests — one driving a touch drag, one a wheel scroll — each sending a steep 2px-horizontal / 150px-vertical scroll at a scroll-axis-lock: none container and asserting the horizontal component is applied (within tolerance) instead of being railed to zero; the wheel subtest additionally asserts the dispatched wheel event's deltaX matches the sent delta. In the latest Chrome (experimental) run on wpt.fyi — Chrome 152.0.7977.7, 2026-07-29 — the test passes 2/2 (results). The intent thread answers “Is this feature fully tested by web-platform-tests?” with “Yes” pointing at the same test.

One caveat: the test's <link rel="help"> points at css-scroll-snap-2/#scroll-axis-lock, an anchor that does not exist — the normative text lives in the unmerged css-overflow-5 PR, and neither Editor's Draft renders the property yet (both fetched 2026-07-29). Treat the test's help link as stale, not as evidence of a second spec home.

Source: WPT scroll-axis-lock.html; wpt.fyi results; Intent to Prototype and Ship

browser compatibility

Interim table. There is no BCD entry (BCD css/properties/ has no scroll-axis-lock.json, verified 2026-07-29) and no web-features entry (webstatus.dev query, zero matches). Rows are compiled from the linked primary sources, not from BCD.

BrowserSupportEvidence
Chrome153 — Enabled by default per the listing; runtime flag ScrollAxisLock still experimental at trunk (2026-07-29), rollout per the intent is “enabled for all users”milestone listing; flag record; intent rollout plan
EdgeNot separately reportedChromium-based; no separate position on the API record
FirefoxNo signalMozilla #1435 (open at fetch time; position not recorded)
SafariNo signalWebKit #698 (position not recorded at fetch time)

Web developer signal on the intent is “Positive”, citing supporting feedback on csswg-drafts #13207. The intent records support on all six Blink platforms (Windows, Mac, Linux, ChromeOS, Android, Android WebView).

Source: chromestatus.com/feature/5908461532610560; Intent to Prototype and Ship

security and privacy

Source: explainer — security and privacy considerations

specifications

DocumentStatus
w3c/csswg-drafts PR #14152 — [css-overflow-5] Introduce scroll-axis-lockOpen, unmerged (fetched 2026-07-29) — the normative propdef and value definitions quoted on this page; targets CSS Overflow Module Level 5, whose Editor's Draft does not yet render the section
w3c/csswg-drafts #13207 — [css-overflow-5] Allow controlling scroll axis locking behaviorAdopted by CSSWG resolution, 2026-01-28 (“scroll-axis-lock:auto|none, applies to scroll containers, not inherited, UNLESS smfr objects”)
scroll-axis-lock explainer (proponents: Blink Interactions)The design document: use cases, rejected alternatives, accessibility & security considerations
w3ctag/design-reviews #1248 — CSS scroll-axis-lockOpen — TAG review status “Pending” on the intent (fetched 2026-07-29)
Source: repository contents fetched 2026-07-29

see also