CSS テーブル(表)の見出し部分(一部)を固定してスクロールする方法

サイトで、表(テーブル)を使って表示したいことがあると思いますが、行の幅が横長になり、スペースに入り切らなかったり、縦の列も長くなりすぎて、デザイン上や見た目あまりよろしくないことがあるかと思います。
そこで、HTML の表(テーブル)が、「Excel のウィンドウ枠の固定」のように、見出し部分のセルだけ固定してスクロールできないものか調べてみた結果、CSSプロパティの「position: sticky;」を使用すれば、比較的簡単に実装できたので、ここに記載しておきます。

下記それぞれ4つのパターンのソースコードがありますが、本サイトで使用している「Wordpress + テーマ(Lightning)」では、一部の「CSS」が反映されないところがあるため、掲載している「HTML、CSS コード」は、一般的にHTMLサイトで反映されるコードを記載しています。

しかし、CSSデザインが異なるテーブルを複数設置する場合は、CSSコードの競合を防ぐために、セレクタ「table、 th、td」や class名「.fixed01」などすべてに「table.クラス名」を付与しています。

CSSコードの記述が、一般的なHTMLサイトと当サイトと異なる点については、以下で説明しています。

【1】テーブルの行(横軸)を固定してスクロールする

見出し 見出し 見出し
テキスト テキスト テキスト
テキスト テキスト テキスト
テキスト テキスト テキスト
テキスト テキスト テキスト
テキスト テキスト テキスト
テキスト テキスト テキスト

縦にスクロールしてみてください。
上部の「見出し(th)」だけが固定され、他の要素(td )はスクロールしていることが確認できると思います。

1行目を固定 HTMLコード ↓

HTMLコードは、上記のソースコードそのままを記載しています。

 

1行目:「<div class=”fixed-box-yoko”>」は、テーブルがはみ出さないように枠を設定しました。
枠からはみ出す部分(下方)は、右のスクロールバーで確認できます。
2行目からのHTMLテーブルタグは、スクロールさせるため行を多めに設定していますが、シンプルな記述となります。
しかし、このページのように、CSSデザインが異なるテーブルを複数設置する場合は、CSSコードが競合するため、テーブルに「class名(”yoko”)」を設定しています。

1行目を固定 CSS コード ↓

 

1~7行目は、テーブルはみ出さないためのBOX です。
19行目の「table.yoko .fixed01」ですが、「table.yoko」は、テーブルのデザインを複数設定しているためテーブルの「class名(”yoko”)」を付与しています。

肝心なのは、「.fixed01」に指定しているプロパティです。

20行目の 「position: sticky;」は「指定された場所までいくと固定」される仕様となっています。
画面上部で固定したいので、「top: 0;」(21行目)で場所を指定しています。

一応このプロパティだけで動作するようですが、「.fixed01」に枠線を指定しても、枠線は固定されずにスクロールされてしまいます。
その結果、スクロールされている要素が後ろでチラっと見えてしまいます。
それを隠すために、追記で「:before」を追加して、固定している要素に枠線を配置しています。
これでスクロールしても「td」の要素が見えることはなくなります。

当サイトとの表示の違いについて

【1】33行目の「border: 1px solid #ccc;」ですが、一般的なHTMLサイトでは、この記述で問題なく「見出しのセルは1px」で表示されるのですが、当サイトでは、上記の記述ですとなぜか見出しのセルのボーダーが重ならず2本線になってしまいます。
10行目の「border-collapse: collapse;」(隣接するセルのボーダーを重ねて表示)が効かないのです。
よって、当サイトでは、ボーダーをトップのみ表示「border-top: 1px solid #ccc;」と記述することで、「見出しのセルのボーダーは1px」で表示されるようになりました。

【2】テーブルタグの「<th>」は、本来一般的なブラウザでは、「太字、中央表示」になるはずなのですが、なぜか当サイトでは機能しないため、当サイトCSSでは、「.fixed01」に「font-weight: bold;」「text-align: center;」を記述しています。

【1】テーブルの行(横軸)を固定してスクロールを見てみる ↑

【2】テーブルの列(縦軸)を固定してスクロールする

見出し テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト

横にスクロールしてみてください。
左端にある「見出し」要素(th)の部分だけ固定されて、右側の(td)の要素はスクロールされることが確認できると思います。

1列目を固定 HTMLコード ↓

 

上記の「行(横軸)を固定してスクロール」と同じで、
1行目:「<div class=”fixed-box-tate”>」は、テーブルがはみ出さないように枠を設定しています。

2行目からは、上記と同様にシンプルなテーブルタグとなります。
固定させたい要素(th)に「fixed01」クラスを付与します。
※(4、12、20、28、36行目)

CSSコードの競合を防ぐため、テーブルに「class名(”tate”)」を設定しています。

1列目を固定 CSSコード ↓

 

1~7行目は、BOXです。
21行目以降:「.fixed01」に「position: sticky;」を指定し、画面の左端で要素(th)を固定したいので「left: 0;」を指定しています。

ここでも後ろでスクロールしている要素を隠すため、「:before」で固定している要素に枠線を追加しています。

当サイトでの表示の違いについて

【1】36行目の枠線も上記同様、この記述で一般的なHTMLサイトでは、問題なく表示されるのですが、当サイトでは、何故か、2本線となりスッキリしないためボ-ダーを左側のみ表示「 border-left: 1px solid #ccc;」と少し記述を変更しています。
これで、見出し部分の隣接するセルのボーダーが「1px」となりスッキリしました。

【2】上記の横軸固定のテーブルと同様に、テーブルタグの「<th>」は、当サイトでは機能しないため、当サイトCSSでは、「.fixed01」に「font-weight: bold;」「text-align: center;」を記述しています。

【3】テーブルの「行(横軸)」と「列(縦軸)」どちらも固定してスクロールする

見出し 見出し 見出し 見出し 見出し 見出し 見出し 見出し
見出し テキスト テキスト テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト テキスト テキスト
見出し テキスト テキスト テキスト テキスト テキスト テキスト テキスト

一番上の見出し部分と左端の見出し部分両方を固定していますので、「縦・横」にスクロールできると思います。

行・列の両方を固定 HTML ↓

 

4行目:左上に来る見出し要素(th)にだけ「fixed01」クラスを付与して、残りの固定したい見出し要素(th)には「fixed02」クラスを付けています。

行・列の両方を固定 CSS ↓

 

上記と同様に1行目~7行目までは、テーブルを入れるためのボックスです。
8行目:テーブルに「yoko-tate」というクラス名をつけています。

20~24行目:「.fixed01」と「.fixed02」のCSSプロパティは今までのものとほとんど同じですが、左上基準で固定するようにしていますので、ポジションは「top: 0;」と「left: 0;」を指定しています。

それと39行目:「.fixed01(左上の見出し)」がスクロールしたときに隠れないように「z-index: 2;」を指定しています。

当サイトでの表示の違いについて

【1】すでに気づいているとは思いますが、見出しの枠線が、2重(2本)になっています。
【3】テーブルの「行(横軸)」と「列(縦軸)」どちらも固定の表示を確認してみる

36行目の「border: 1px solid #ccc;」で、今までと同様に一般的なHTMLサイトでは、問題なく表示されています。
「HTML サイト」での表示はこちらから確認できます。

上は画像ですが、HTML のサイトでは、ちゃんと「border-collapse: collapse;」が機能して、見出しの枠線(border)が、「1px」で表示されているのが確認できると思います。

結果、いろいろ調べて見ましたが、修正方法はわからなかったため、仕方なく「見出しの枠線が、2重(2本)」になったまま掲載しているということです。

【2】上記2種類のテーブルと同様に、テーブルタグの「<th>」は、当サイトでは機能しないため、当サイトCSSでは、「.fixed01」に「font-weight: bold;」「text-align: center;」を記述しています。

【4】テーブルの「列(縦軸)」を途中で固定する

見出し テキスト 固定 テキスト テキスト テキスト テキスト テキスト
見出し テキスト 固定 テキスト テキスト テキスト テキスト テキスト
見出し テキスト 固定 テキスト テキスト テキスト テキスト テキスト
見出し テキスト 固定 テキスト テキスト テキスト テキスト テキスト
見出し テキスト 固定 テキスト テキスト テキスト テキスト テキスト

右にスクロールしてみてください。「固定」と書かれている要素が途中で固定されます。

「列(縦軸)」を途中で固定する HTML ↓

 

1行目:「<div class=”fixed-box-tatetocyu”>」は、テーブルがはみ出さないように枠を設定しました。
2行目からのHTMLテーブルタグには、CSSの競合を防ぐため「class名(”tatetocyu”)」を設定しています。

左側で固定する要素に「fixed01」を付与して、途中で固定したい要素に「fixed02」を付与しています。

「列(縦軸)」を途中で固定する CSS ↓

 

ここもCSSのプロパティはほぼ同じです。

異なる点はポジションの指定をしているところで、
25行目:一番左側に固定する要素「.fixed01」には「left: 0;」。
31行目:途中で固定する要素「.fixed02」には「left: 199px;」を設定しています。

「th、td」の幅が「200px」なのになぜ、「left: 199px;」なのかと言いますと、「left: 200px;」にしてしまうと、枠線が隣り合わせになってしまい「2重(2本)」線になってしまうからです。

試しに「left: 200px;」と書き換えて表示させてみてください。そのほうが理解しやすいかと思います。

当サイトでの表示の違いについて

【1】41行目の枠線も上記【1】【2】のテーブル同様、当サイトでは、何故か、2本線となりスッキリしないためボ-ダーを左側のみ表示「 border-left: 1px solid #ccc;」と少し記述を変更しています。
これで、見出し部分の隣接するセルのボーダーが「1px」となりスッキリしました。

【2】上記の固定のテーブルと同様に、テーブルタグの「<th>」は、当サイトでは機能しないため、当サイトCSSでは、「.fixed01」に「font-weight: bold;」「text-align: center;」を記述しています。

まとめ

当サイトの「Wordpress + lightning 」と一般的な「HTMLサイト」との表示が異なるため、少し苦戦しましたが、それを除けば、「position: sticky;」を使って、比較的簡単にテーブルの一部を固定してスクロールすることができるのを確認できたと思います。

今のところ「Chrome」と「FireFox」「Edge」でサポートされているようです。ただし、
※Chromeでは「thead」と「tr」要素で「sticky」が使えないとのこと。
※Safariではプレフィックスが必要です(-webkit-sticky)。
また、「IE」ではサポートさていないとのことですので注意が必要です。