CSSだけで横スクロールと見出し固定を両立! 単一軸スクロールコンテナー

はてなブックマークへ投稿
Xへポスト
URLをコピー
共有

Chrome・Edge 156(2026年10月)では、overflowプロパティの機能が拡張され、単一軸スクロールコンテナー(Single-axis scroll containers)に対応しました。これにより、position: sticky;の追従する要素を横方向と縦方向で分けられるようになりました。

実現したいこと

ウェブページ上の表を考えてみましょう。表がブラウザの幅からはみ出すぐらい横長の場合、表の中を横スクロールさせて全体を確認できるようにします。左側に表の見出しがあれば、スクロール時に位置が固定されている方が内容を読み取りやすいです。

表が縦に長い場合、通常は表の中を縦スクロールします。ウェブページ全体の縦スクロールとは別に、表の中を縦横のスクロールコンテナーとして表示させます。

今回実現したいのは、横スクロール時は表の内部をスクロールさせて左の見出しを固定しつつ、表の中の縦スクロールはページのスクロールと連動させる(表の中のスクロールではない)動きです。その際、表の上部の見出しはページの上端に固定します。

単一軸スクロールコンテナーに対応する前は、左見出しを固定できても、上見出しはページの縦スクロールとともに画面の外へ流れてしまいました。この挙動をCSSだけで実現できるようになります。

次の章から、従来の方法で両立できなかった理由と、新しい仕様を詳しく見ていきましょう。

なぜ固定見出しの両立が実現できないのか

表を横方向にスクロールさせるためoverflow-xにauto/scrollを指定した場合、たとえ縦のスクロールが発生していなかったとしても、縦方向もスクロールコンテナーとしてあつかわれました。overflow-yの場合も同様です。

position: sticky;はスクロールに合わせて要素を固定するCSSですが、自分の祖先にスクロールコンテナーがあると、そのコンテナーの領域が基準になります。

そのため、祖先要素にスクロールコンテナーがある要素にいくらposition: sticky;を指定しても固定位置の基準はスクロールコンテナーになってしまいます。横方向は表の中でスクロール、縦方向はページに対してstickyをしたくても、これらを分けて考えることはできませんでした。

下のデモでは親要素に高さを設定しており、内側を縦スクロールすれば上見出しをそのスクロール領域の上端に固定できます。ただし、ページの縦スクロールには追従しません。

単一軸スクロールコンテナーが何を可能にしたのか

overflowプロパティにスクロール可能な値とclipを組み合わせたときの動作が更新されました。それにより、指定した軸(この場合は横)だけがスクロールコンテナーになります。縦方向はスクロールコンテナーにならないため、position: sticky;はページ全体のスクロールに連動できます。具体的には、次のように指定します。

overflow: auto clip;
/*
  以下の指定と同じ意味
  overflow-x: auto;
  overflow-y: clip;
*/

overflow: auto clip;のように片軸だけにclipを指定した場合、単一軸スクロールコンテナーに対応しないブラウザーはhiddenを指定したものとみなします。つまり、片軸だけにclipを指定しても指定通りには動きません。

以下の図は、tableの親要素のoverflow-yがhiddenの場合とclipの場合で、縦横それぞれのスクロールコンテナーがどう変わるかを示しています。

position: sticky;は、直近の祖先スクロールコンテナーを基準に固定されます。この例では、overflow-yの値によって縦方向の基準が次のように変わります。

  • overflow-y: hidden;(従来)

    親要素が縦方向のスクロールコンテナーになるため、ページを縦にスクロールすると上見出しも親要素ごと移動し、画面上部に固定できません。

  • overflow-y: clip;(今回の仕様)

    親要素が縦方向のスクロールコンテナーにならないため、さらに祖先にあるスクロールコンテナーが基準になります。この例ではページ全体の縦スクロールに連動し、上見出しを画面上部に固定できます。

これにより、左見出しは表を横スクロールしたときに左端に固定し、上見出しはページを縦スクロールしたときに画面上部に固定できます。

この指定とposition: sticky;を組み合わせた動きを、次のデモで見ていきます。

デモ①:工程表

※注意:本記事のデモは、Chrome・Edge 156以上でご覧ください。

上と左の見出しを固定した工程表です。左見出しはテーブルに、上見出しは画面上部に固定しているのがポイントです。

1列目と2列目には、それぞれscope="rowgroup"とscope="row"を指定しています。行見出し固定時に重ならないよう、2列目は1セル分右側に固定しています。

.table-scroll {
  overflow: auto clip; /* 横方向だけスクロールさせる */

  thead {
    th {
      position: sticky; /* 列見出しを画面上部に固定 */
      top: 0;
    }
  }

  tbody {
    th[scope="rowgroup"] {
      position: sticky; /* 行見出しをテーブル左側に固定 */
      left: 0;
    }

    th[scope="row"] {
      position: sticky; /* 行見出しをテーブル左側に固定 */
      left: 160px; /* 1セル分右側で固定させる */
    }
  }
}

.table-scrollにoverflow: auto clip;を指定すると、この要素は横方向だけのスクロールコンテナーになります。縦方向にはスクロールコンテナーが作られないため、上見出しのposition: sticky;は.table-scrollではなくページ全体のスクロールに追従し、画面上部に固定されます。

デモ②:国別比較テーブル

次のデモは、単一軸スクロールコンテナーとscroll-state()を組み合わせた国別比較テーブルです。縦横の見出しの固定状態に応じて、文字サイズの変更や影の表示など、スタイルを切り替えています。

scroll-state()は、スクロールの可否やposition: sticky;の固定状態を判定できるコンテナークエリーです。基本的な使い方は記事『スクロールの状態変化でスタイル切替が可能に! CSSコンテナークエリーのscroll-state()入門』をご覧ください。

.table-scroll {
  overflow: auto clip; /* 横方向だけスクロールさせる */
  container-type: scroll-state; /* スクロール状態を判定可能に */
  container-name: table-scroll; /* テーブルの参照名 */

  table {
    thead {
      position: sticky; /* 列見出しを上部に固定 */
      top: 0;
      container-type: scroll-state; /* スクロール状態を判定可能に */
      container-name: column-heading; /* 列見出しの参照名 */

      th {
        @container column-heading scroll-state(stuck: top) {
          .country-heading {
            .country-flag {
              grid-template-columns: 1fr;
            }
          }
        }
      }
    }

    tbody {
      th {
        position: sticky; /* 行見出しを左側に固定 */
        left: 0;
      }
    }
  }

  .scroll-shadow {
    /* 右方向にまだスクロールできる場合 */
    @container table-scroll scroll-state(scrollable: right) {
      opacity: 1;
    }
  }
}

対応ブラウザ

CSSのoverflowプロパティによるSingle-axis scroll containersは、Chrome・Edge 156(2026年10月)以上で利用可能です。

参照:Can I use…

まとめ

単一軸スクロールコンテナーを紹介しました。機能自体に派手さはないかもしれませんが、活用すればUXを高めることができます。実装に手間がかかっていた表現をCSSのみでシンプルに記述できるので、ぜひ活用してみてください。

Google検索でICS MEDIAの記事を見つけやすくしよう

優先するソースに追加すると、GoogleのトップニュースやAI検索でICS MEDIAの記事が表示されやすくなります。

Googleで優先するソースとして追加
SNSでシェアしよう
シェアいただくと、サイト運営の励みになります!
はてなブックマークへ投稿
Xへポスト
URLをコピー
共有
山本 竜也

フロントエンドエンジニア。フロントエンド開発がどんどんおもしろくなり、ICSに入社しました。体力には自信があります。

この担当の記事一覧