かわいいエイのイラスト

CSS の scroll-axis-lock で斜め方向にスクロールできる UI を作る

ブラウザはスクロール操作の方向を縦か横の一方向に固定することがあります。scroll-axis-lock プロパティを使うと、この軸ロックを解除できます。この記事で scroll-axis-lock の基本的な使い方を紹介します。

地図やスプレッドシートをトラックパッドでスクロールしているとき、斜めに動かしたつもりが縦方向にしか動かなかったことはないでしょうか。ブラウザは操作の開始方向からユーザーの意図を判断し、スクロールを縦か横の一方向に固定することがあります。この動作を「軸ロック」と呼びます。

軸ロックは、縦に読み進めているときに意図せず横へずれることを防ぎます。一方で、地図のように縦横を自由に移動したい UI では操作の妨げになる場合があります。

CSS の scroll-axis-lock プロパティを使うと、スクロール領域ごとに軸ロックを解除できます。この記事では基本的な使い方を紹介します。

Note

2026 年 9 月 22 日現在、scroll-axis-lock は Chrome 153 の新機能として提供されています。仕様は CSS Overflow Module Level 5 の Editor's Draft です。

スクロールの軸ロックとは

例えば、指をほぼ縦方向に動かす操作には、わずかな横方向の動きも含まれます。この横方向の動きを厳密にスクロールに反映させると、ユーザーの意図とは異なるスクロールが発生することがあります。そのため、ブラウザが「縦へスクロールしたい」と判断すると、横方向の移動量を無視することがあります。これを軸ロックと呼びます。

仕様の説明では、縦方向の移動量が 500px、横方向の移動量が 3px という例が挙げられています。ブラウザが縦方向に軸ロックした場合、横方向の 3px はスクロールに反映されません。

縦に読み進めるときには便利ですが、地図やスプレッドシート、キャンバスのように縦横を自由に移動したい UI では、軸ロックが操作の妨げになる場合があります。軸ロックによってその動きが制限されると、一度指を離して別の角度から操作し直す必要が生じます。

scroll-axis-lock: none は、このような入力を一方向へ固定する処理を無効にします。縦横両方向の入力がある場合に、その横方向の成分を軸ロックによって無視されないようにします。

scroll-axis-lock の使い方

スクロールする要素に scroll-axis-lock: none を指定します。

.table-container {
  width: 420px;
  height: 360px;
  overflow: auto;
  scroll-axis-lock: none;
}

overflow: auto は、内容がはみ出したときにスクロールできる領域を作ります。その要素に scroll-axis-lock: none を追加すると、ブラウザによる軸ロックを解除できます。縦横にスクロールするためには、内容が両方向にはみ出している必要があります。

指定できる値は次の 2 つです。

値 意味
auto ブラウザは軸ロックしてもよい。初期値
none ブラウザは軸ロックしてはならない

Note

auto は軸ロックを強制する指定ではありません。どのような操作で固定されるかは、ブラウザや入力デバイスに依存します。

Warning

親要素に scroll-axis-lock: none を指定しても、子要素には自動で継承されません。実際にスクロールする要素へ指定する必要があります。

なぜ新しいプロパティが必要なのか

最初の提案では、地図や大きな図などの 2 次元の UI で、軸ロックが自由な移動を妨げることが課題として挙げられています。

Explainerでは、既存の回避策として JavaScript で指の移動量を追跡し、位置を更新する実装が紹介されています。ただし、この方法ではジェスチャーの処理を自前で管理しなければなりません。JavaScript を実行するメインスレッドがほかの処理で忙しい場合、操作への反応も遅れる可能性があります。

const container = document.querySelector(".table-container");
let previous = null;
 
container.addEventListener("touchstart", (event) => {
  const touch = event.touches[0];
  // 1 本指の操作だけを対象に、移動量の基準となる座標を記録する
  previous =
    event.touches.length === 1 ? { x: touch.clientX, y: touch.clientY } : null;
});
 
container.addEventListener(
  "touchmove",
  (event) => {
    if (!previous || event.touches.length !== 1) return;
    // ブラウザの標準のスクロール処理を無効にし、自前でスクロール位置を更新する
    event.preventDefault();
 
    const touch = event.touches[0];
    container.scrollLeft += previous.x - touch.clientX;
    container.scrollTop += previous.y - touch.clientY;
    previous = { x: touch.clientX, y: touch.clientY };
  },
  { passive: false },
);
 
const reset = () => {
  previous = null;
};
container.addEventListener("touchend", reset);
container.addEventListener("touchcancel", reset);

このような JavaScript による回避策の問題点を解決するために、標準の CSS で軸ロックの挙動を制御する scroll-axis-lock プロパティが提案されました。

Note

初期案の名前と値は overflow-axis-lock: proximity | none でした。2026 年 1 月の CSSWG の議論で、初期の動作をブラウザの判断に委ねる auto と、スクロールの制御を示す scroll- という名前に変更されました。

大きな表で操作を比較する

実際にどのような違いがあるかを確認してみましょう。同じ内容の表を 2 つ並べ、片方だけに scroll-axis-lock: none を指定して比較します。

違いを確認するためにはトラックパッドで縦方向にスクロールしてみるとわかりやすいです。scroll-axis-lock: none を指定していない方は真っ直ぐにスクロールされる一方で、scroll-axis-lock: none を指定した方はわずかに横方向にずれながらスクロールされることがわかります。

まとめ

  • scroll-axis-lock: none は、ブラウザがスクロールを縦か横の一方向に固定する軸ロックを解除する
  • 初期値の auto はブラウザの判断に委ねる指定であり、軸ロックを強制しない
  • scroll-axis-lock は継承されないため、実際にスクロールする要素へ指定する

参考

記事の理解度チェック

以下の問題に答えて、記事の理解を深めましょう。

scroll-axis-lock の初期値 auto は、どのような指定ですか?

  • ブラウザが軸ロックすることを許可する

    正解!

    auto は軸ロックをブラウザの判断に委ねます。すべての操作で軸ロックが発生するわけではありません。

  • 縦か横の一方向への固定を強制する

    もう一度考えてみましょう

    auto は軸ロックを強制しません。現在の仕様に強制用の値は定義されていません。

  • 入力にかかわらず斜め方向へ動かす

    もう一度考えてみましょう

    scroll-axis-lock は入力方向を変換する機能ではありません。auto は軸ロックを許可します。

  • 縦方向の軸ロックだけを解除する

    もう一度考えてみましょう

    auto は特定の軸のロックを解除する指定ではありません。軸ロックを解除する値は none です。