勉強日記

チラ裏

ブラウザ上端にひっつくテーブル見出し

github.com

https://github.com/wand2016/misc/raw/master/sticky_table_header/sticky_table_header.gif

  • 必要になったので

動作環境

しくみ

  • 同じ内容のテーブルを2枚重ねているうんこ実装だったのをテーブル1枚+CSSのtransformにリプレース
  • <td>,<th>のborderはtransformに追従してくれないので、td::after疑似要素を使ってborderを描いている
.cell {
    position: relative;
    box-sizing: border-box;
}

.cell::after {
    position: absolute;
    content: '';
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    border: 1px solid gray;
    box-sizing: border-box;
}
  • まじめにやるなら、borderはleftとtopだけに設定すべき
  • scrollイベントで矩形判定する
const headerCells = Array.from(document.querySelectorAll('tr.top-header .cell'));

window.addEventListener('scroll', function () {
    headerCells.forEach(function(headerCell) {
        tableRect = document.querySelector('table').getBoundingClientRect();

        // テーブルが画面上にはみ出したら、
        // はみ出した分だけテーブル見出しをy方向にずらす
        if (tableRect.top < 0) {
            headerCell.style.transform = 'translate(0, ' + -tableRect.top +'px)';
        }
        else {
            headerCell.style.transform = '';
        }

        // テーブルが画面外に出たら、テーブル見出しを非表示にする
        if (tableRect.bottom < 0) {
            headerCell.style.visibility = 'hidden';
        }
        else {
            headerCell.style.visibility = '';
        }
    });
});
  • テーブルが画面上にはみ出したら、その分だけテーブルヘッダをy方向にtranslateして相殺する
  • テーブルが完全に画面外に出たら、テーブルヘッダを非表示にする