hyiromori’s tech blog

Webエンジニア hyiromori の技術ブログです。

CSSだけでテーブルの縦横2列を固定してスクロールできるようにする

はじめに

タイトルのような、とても大変な要件のテーブルを作って欲しいという要望があったので、その際に試行錯誤した結果を記録しておいたエントリです。

サンプル

CodePenで作ったサンプルです。

See the Pen ScrollTable with fixed 2rows & 2columns header. by hyiromori (@hyiromori) on CodePen.

コードの解説

このコードではposition: stickyを使用することで、テーブルの行、列を固定しています。

position: stickytop right bottom left と組み合わせて使うことで position: relativeposition: absoluteを組み合わせたような動きが可能になる指定です。

Safari ではposition: -webkit-sticky;のようにベンダープレフィックスをつけないと動作しませんでした。

詳細はMDNの解説をご覧ください。

position: sticky の対応状況

Can I Useによれば、モダンブラウザは対応済みです。 ちなみにChromeなどは

Supported on th elements, but not thead or tr

とある通りthead trにバグがあるようです。 このサンプルはthead trに指定していないので、対応ブラウザなら正常に動作するはずです。

幅と高さの制約

position: sticky を使用するため、一部のセルは幅または高さを固定する必要があります。 今回のサンプルは、縦横それぞれ2列を固定するため、以下を固定しなければなりません。

  • 1行目の高さ(2行目のtopを指定しないと固定できないため)
  • 1列目の幅(2列目のleftを指定しないと固定できないため)

実際に使用する場合は、これらのセルを指定した幅と高さで必ず収まるように要素を配置しないといけません。

表示上の制約

テーブルの親要素の幅が十分に広い場合、右側に余白ができてしまう場合があります。 これは table {width: 100%} を指定しても解消できませんでした。

WindowのResizeイベントMutationObserver を使って、 ある程度の幅以下になったら横スクロールを適用するという方法で乗り切りました。

ResizeObserverも使えますが、まだまだ対応ブラウザが少ないです。 対応ブラウザが増えたらこちらも使えるかもしれません。