v153 · css · scrolling

scroll-axis-lock

Start a scroll gesture mostly sideways and the browser will usually decide you meant sideways, zeroing the perpendicular movement for the rest of the gesture. That is the right call for a page and the wrong one for a map. scroll-axis-lock: none is how a scroll container says so.

concepts

  1. Does this browser know the property?

    Two keywords, one initial value, and a parser that must reject anything else. Type a value and see whether it parses, what it computes to, and whether the element it is on is even a scroll container.

  2. Recording a real gesture

    Scroll one of two panes and every scroll event is recorded with its per-axis delta. A locked gesture leaves a run of events with one axis at exactly zero — which is a thing you can count, not a thing you have to feel.

  3. Panning a map

    The use case: a board bigger than its viewport where the target is diagonally away from you. Drag both panes and compare the paths they traced — one bends into an L, the other goes where you pointed.

why it shipped

Axis locking exists because most scrollers are documents, and a document scrolled diagonally by a slightly crooked swipe feels broken. Committing the gesture to whichever axis it started on removes that drift, and it has been the default long enough that few people know it is happening.

It stops being helpful the moment the content is two-dimensional. A zoomed photo, a seating plan, a spreadsheet, a tile map, a node graph: the diagonal is not drift, it is the movement. Locking turns one gesture into two and makes the content feel like it is fighting the finger. The property is the narrow fix — the scroll container that knows it is two-dimensional says so, and everything else keeps the default.

the CSS

.map {
  overflow: auto;
  scroll-axis-lock: none;   /* the user agent must not lock to one axis */
}

/* The initial value, and what every other scroller keeps. */
.article {
  scroll-axis-lock: auto;   /* the user agent may lock to one axis */
}

Two keywords, no shorthand, discrete animation, and it applies to scroll containers. auto is permission, not a promise: it says the browser may lock, which is why the effect varies by input device and platform.

enabling it now

Verified on Chrome 150 on this machine: with the flag off, CSS.supports("scroll-axis-lock", "none") is false and the declaration is dropped. With it on, both keywords parse, an invalid keyword is correctly rejected, and the computed value round-trips.

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

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

Note what the flag does not settle: whether a given device locks in the first place. auto permits locking rather than requiring it, so a mouse wheel, a trackpad and a touchscreen can all behave differently on the same page — which is why the demos here measure the gesture you actually make rather than describing one.

references