4 ポイント 投稿者 GN⁺ 2024-02-25 | 1件のコメント | WhatsAppで共有
  • 行数の多いテーブルは、スクロールするほど列の意味を忘れやすくなり、データが読みづらくなる
  • theadposition: sticky;top: 0; を追加するだけで、ヘッダー固定を実装できる
  • sticky は世界全体で約 96% のブラウザ対応があり、実験的機能に近いものではない
  • 300番目の項目のような下の行を見ているときでも列見出しが残るため、表の閲覧体験が向上する
  • 実装は小さいのに効果は大きく、長いテーブルを提供するWebページなら基本的な使いやすさ改善として適用する価値がある

長いテーブルでヘッダーが消える問題

  • 大きなデータセットや数百行あるテーブルでは、スクロール後にテーブルヘッダーが画面外へ消えてしまう
  • 300番目の項目まで下がると、各列のデータが何を意味するのかを再確認しづらくなることがある
  • 初見のテーブルほど列の意味を覚えながら読む必要があり、閲覧の負担が大きくなる

thead に sticky を適用する

  • 解決方法は thead に2つのCSSプロパティを追加すること
position: sticky;
top: 0;
  • position: stickytop: 0 を組み合わせると、スクロール中でもヘッダーを画面上部に固定できる
  • sticky は約 世界全体で96% の対応率があり、多くのブラウザで利用できる
  • 実際の動作は CodePen の例 で確認できる

1件のコメント

 
GN⁺ 2024-02-25
Hacker News のコメント
  • 一方の軸だけの固定ヘッダーならよいが、CSS が両軸をサポートする日をいまだに待っている: https://github.com/w3c/csswg-drafts/issues/8286

    • 列とヘッダーの両方を固定しなければならなかった受託案件は、これまでで最も難しい仕事のひとつだった 標準的なテーブルなら簡単だが、これは生成された CSS-as-JS を使う複雑なVueJS のサードパーティ製動的テーブルで、CSS と JS がどこから来ているのかを突き止めるだけでもかなり時間がかかり、結局は JS のクラス関数と生成された CSS を上書きする羽目になった クライアントには時間がかかりすぎて申し訳なく思ったし、Vue/React のコードベースではライブラリ選定をずっと慎重にするようになった。テーブルは HTML の基本要素なのに、なぜ単純な作業ひとつに JS クラス三重構造と JSON でインポートした CSS まで必要なのかわからない
    • この問題の元になった元々の issue をたぶん8年間見続けているが、CSS 仕様の中でも最もいら立たしい部分だ ときには巨大なデータテーブルが必要で、上部を固定しつつ overflow-x: auto も使いたいのに、どちらか一方しか選べないと言われる
  • 正直に言うと、CSS の知識がほとんどなくてもそれなりに動く Web アプリは作れてしまっている。最近、約2万行の怪物テーブルでヘッダーを固定しようとしていた: https://www.datasciencemeta.com/rpackages 最初は Bootstrap のテーブルクラスに class="table table-header-sticky" みたいなものがあると期待したがなかったし、Stack Overflow、GPT、CodePen の提案を 20 分ほどいじっても妙な副作用が出た ところがこの記事の CodePen では 2 分で動き、今まさに本番へデプロイしているところだ

  • テーブルヘッダーの固定は position: sticky; ひとつで簡単そうに見えるが、テーブル内容に何かを追加し始めるとすぐ複雑になる 固定ヘッダー付きのテーブルで、ユーザーが本文をスクロールしてページを離れたときに最初に見えていた行のインデックスを保存し、戻ってきたときに復元する機能を付けたのだが、いつも 1 行ほど下にずれて復元されていた。調べてみると、5 行目は実際にはテーブル最上部にあったのに、thead が重なっていたせいで 6 行目が最初の行のように見えていた そこで thead の高さを考慮してスクロール位置を調整したが、ときどき数ピクセルずれていた。大きなテーブルなのでスクロールイベントで遅延読み込みをしており、さらにデフォルトの自動テーブルレイアウトを使っていたため、ヘッダーセルが折り返されてヘッダー全体の高さが変わっていたのだ。最終的には theadResizeObserverを付けて、高さが変わるたびにスクロール位置を動的に調整した [1] https://developer.mozilla.org/en-US/docs/Web/API/ResizeObser...

  • これを実装する際、ヘッダーの境界線も一緒に固定したいなら、table thead:beforetable thead:afterposition: absolutewidth: 100%top: 0 / bottom: 0border-top / border-bottom を与える形で対処できる

  • テーブルヘッダーは自動的にこう動いてほしい。開発者がわざわざ関連タグを使って追加作業をしているなら、たいてい既に望んでいる動作はこちらのはずだ

    • すべてのページでユーザー定義スタイルシートを読み込めるブラウザ拡張を入れればよい ただ最近は の代わりに を 500 個、その各 の中に 45 層ネストした でテーブルを作るサイトが増えているので、そういう場所では効かない気がする
    • こういう変更は予想外の形で何かを壊す可能性が高そうだ 主な理由は、CSS Grid が登場する前、多くの Web サイトが表をグリッドレイアウト用に使っていたからだろう。ヘッダーが固定されると、そうしたレイアウトは壊れうる HTML セマンティクスの大きな失敗は、テーブルが「表形式データを表示する方法」ではなく「任意の要素のグリッド」として受け取られてしまったことにある
  • コマンドラインではヘッダーは stderr、本文は stdout に送ればよい そうしなければ heights | sort -k2 -nr の結果は George 186Wally 173NAME HEIGHT の順になるが、ヘッダーが stdout を迂回すれば NAME HEIGHTGeorge 186Wally 173 の順になる

    • heights | (sed -u 1q; sort -k2 -nr) が正しく動く 出典: https://stackoverflow.com/a/56151840
    • ファイルに書き出す場合はもう少し工夫が必要で、シェルへの理解もより求められる これはインバンドなテキスト専用モデルに付きまとう継続的な制約だが、STDERR をこう誤用すると、役立つどころかかえって混乱しそうだ heights がファイルなら % head -1 heights ; sed 1,1d heights | sort -k2 -nr のようにできるし、heights が 2 回実行するには高コストな実行ファイルなら % heights > /tmp/heights ; head -1 /tmp/heights ; sed 1,1d /tmp/heights | sort -k2 -nr のようにできる。awk にパイプしてもよい 別の選択肢は利便性では劣るが、意外性は少なく、実行ファイル作者が別の考えを持っていても動く
    • ここでは何がよりよいのだろうか。ヘッダーを stderr に送ることか、それとも stdout がTTY のときだけヘッダーを出力することか?
  • これは長い間動かなかった。Chrome は以前 theadtr 要素で position: sticky を無効化していた: https://issues.chromium.org/issues/41303743 ブラウザ対応表はほとんど全部緑色に見えたのに、肝心の Chrome のテーブルでは動かなかった記憶がある

    • 今ではここまで簡単になったのが驚きだ。昔必要だった頃は、ブラウザごとに動かすために HTML と CSS にありとあらゆるゴミを入れなければならなかった とはいえ驚きはしない。Web 開発はだいたいいつもそんなものだからだ
  • むしろ「お願いだからやめてほしい」と言いたい側でもある: https://news.ycombinator.com/item?id=32998091

    • 一般的な Web ページなら全面的に同意する。Stylus スタイルを書くより速いので、uBlock Origin で固定要素を消すことが多いし、サイト全体に適用する汎用スタイルもかなりよく効いた ただし元記事は固定ヘッダー列のあるデータテーブルの話なので、この提案は実際かなり有用だ
    • それは Web ページ全体の固定ヘッダーの話だ。テーブルではまったく別の話になる 数字の入った列が 12 列ほどあるテーブルを見ていて、少し下にスクロールしただけで何が何だかわからなくなる状況は本当に嫌だ
    • sticky プロパティの何が悪いのか?
  • CodePen は top を境界線の分だけオフセットすると、もっとよく見える。たとえば 0 の代わりに**-1px** にすると、テーブル本文がヘッダーの上に透けて見えるのを避けられる 比較: https://codepen.io/bradleytaunt/pen/bGZyJBj 修正版: https://codepen.io/alokmenghrajani/pen/ExMBQow

  • 固定ヘッダーの代わりに制限されたビューポート高さを使って、ヘッダーが常に見えるようにする方式を提案する DataGridXL(https://datagridxl.com) のようにすればよい。ちなみに私が作ったものだ

    • ふと思っただけだが、この方式はポインティングデバイスなしで、たとえばキーボードだけで操作するのがかなり難しい
    • 批判したいわけではないが、モバイルではこういう方式を好きになれたことがない。コンテンツはページと一緒にスクロールすべきだと思う