メモの日々


2019年04月17日(水) [長年日記]

[web] テーブルにスクロールバーを付ける (2)

HTMLのtable要素で作るテーブルが縦に長い場合に、テーブルにスクロールバーを表示しかつスクロールしても行ヘッダが見えたままになるようにしたい。できればJavaScriptは使わずに。

14年前に同様のことをメモしたのだけれど、そのときの結果を今試しても想定通りには動かない。

CSSの「position: sticky」を使うと実現できるようなのでメモしておく。動作はFirefox 66とChrome 73で確認。

テーブルの高さが固定の例

テーブルの高さを固定にする場合はわりと簡単に実現できた。

スクロールバーはtable要素ではなくそれを囲むdiv要素が表示することに注意。HTMLとCSSを抜粋すると次のような感じ。

    <div class="table-wrapper">
        <table>
        ...
        </table>
    </div>
    .table-wrapper {
        display: inline-block;
        height: 300px;
        overflow: auto;
    }
    th {
        background-color: orange;
        position: sticky;
        top: 0;
    }
  • テーブルの高さを決める要素(上の例ではclassがtable-wrapperのdiv要素)にCSSでheightを設定し、table要素はこの要素の中に配置する。
  • th要素にCSSでstickyを設定する。
  • そのままだとスクロールした時にテーブルのヘッダとボディの文字が重なって表示されてしまうので、th要素には背景色を設定する。
  • table-wrapperクラスをinline-blockにしているのは、幅を内容(table要素)の幅に合わせるため。ただ、こうするとFirefox 66ではテーブルの幅が狭くなりすぎてしまう模様。

なお、Firefox 66ではヘッダのセル間に線を描画するためにtable要素のborder-collapseをseparateにする必要があった(上の抜粋には含めていない)。

テーブルの高さをブラウザのウィンドウの高さと連動させる例

テーブルの高さは、固定ではなくブラウザのウィンドウの高さと連動するようにしたいことが多いのでそのケースもメモ。

HTMLとCSSを抜粋する。HTMLは前の例と同じなのだけれど、table-wrapperを囲むdivにもスタイルを設定するのでその部分を含めて抜粋し直す。

    <div class="container">
        <h1>テーブルにスクロールバーを付ける</h1>
        <h2>テーブルの高さがウィンドウの高さに連動する例</h2>
        <div class="table-wrapper">
            <table>
            ...
            </table>
        </div>
    </div>
    .container {
        position: absolute;
        bottom: 10px;
        top: 10px;

        display: flex;
        align-items: start;
        flex-flow: column nowrap;
    }
    .table-wrapper {
        overflow: auto;
    }
    th {
        background-color: orange;
        position: sticky;
        top: 0;
    }
  • table-wrapperの親要素(上の例ではclassがcontainerのdiv要素)に「position: absolute」と「display: flex」を指定する。これにより、table-wrapperの高さがウィンドウの高さと連動するようになる。
  • table-wrapperにはinline-block指定やheightの指定は不要になる。