2012年2月14日火曜日

CSSによるおそらく最も簡単にヘッダとフッタを固定するスクロールテーブルの実装方法

table要素にfloatを指定すると色々と面白い挙動を示すことが分かった.どうやらtbody要素にfloat:leftを指定するとoverflow:autoが有効となるようだ.もう少し確かめないといけないが,何も細かいことをせずヘッダー・フッター固定処理は実装可能かもしれない.
2013/10/04追記

出来た!こいつはヤバい!
テーブルの構造を弄っていない!
divですら囲っていない!
しかもレイアウトが崩れにくい!
cssの記述量が極小!
何よりfirefox,opera,chromeはもちろんie8でも動作する!
更に簡単な方法を編み出した方がおられたので,リンクを貼っておきます.
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1088973685
http://khurata.dtdns.net/QA/q1088973685/
#table01HeadR { float:left; }
#table01Body { float:left; height:200px; overflow:auto; }

わずか2行ですか…凄いね!

2018/01/24追記
CSSプロパティの拡張によりよりモダンなスタイルを指定できるようになってきているようです.
CSSのみで行・列ヘッダ固定テーブルを実装(Firefox / Chrome / Safari)
https://qiita.com/shunsuke_i_anotelia/items/14fb4ec2600828a21a22


    設定方法
  1. table要素の直下のtbody,thead,tfoot要素を省略しない.
  2. tableのwidthにスクロールバーコミコミの幅を設定する.
  3. tbodyにfloat:left,overflow:auto,heightを指定する.
  4. trにfloat:leftを指定する.
  5. th,tdに幅を指定する.
要はtableを構成する要素にfloat属性を指定することで,tableレイアウトのもつ様々な呪縛(幅の自動調整機構やoverflowが無視されるなど.)を解く事ができるのだ.その結果,従来では難しかったレイアウトの制御が自由に行えるようになる.
      注意点
    • colgroup,col要素による幅の設定はできない.
      従って列ごとに幅を指定するには専用のクラスを用意して対処するか,ie8を無視していいならnth-childセレクタを使う.
    • セルの内容が横に膨らんだ場合,そのセルを含む行のレイアウトがずれる.
      ※セルの内容が縦に膨らんだ場合は行自体が勝手に縦に伸びるので対処不要.
      (tr要素における内部のth,td要素の高さ調整機能が活きている)
    • colspan/rowspan属性によるセル結合はほぼ出来ない.
      (無理をすれば出来るかもしれないけれど…)
    • ここから列固定を実現するためにjavascriptを仕込んでみたが,どうにもie8の場合にクラッシュする状況が発生してしまった.この方式ではヘッダー・フッター固定に留めておいたほうが良さそうだ.
    いくつか気になる点もあると思うが,これはtableの機能を再構成する上での代償なのであしからず.以下にサンプルを載せてみる. これ以外にも色々と応用が可能なのでお試しあれ.

    ※ コレをベースに横スクロールしたときに1列目が固定されるようにjavascriptを走らせるサンプルを作ってみた.が,どうにもie8にてクラッシュしてしまう.動かないのはともかくクラッシュはいただけない.ie9では動作確認をしていないので,とりあえず参考までにリンクだけ貼っておきます.ie8回避のコードは組み込んでますが実行する際は注意して下さい…


    12345
    12345
    12345














































    
    <style type="text/css">
    
     /*table*/
     #scrollable2{
      width:380px;/*スクロールバーの幅コミコミ*/
      border-collapse:collapse;
     }
     /*tbody*/
     #scrollable2>tbody{
      height:200px;
      float:left;/*この設定によりoverflowが有効となる*/
      overflow:auto;
     }
     /*tr*/
     #scrollable2 tr{
      float:left;/*この設定によりセル幅が固定化される*/
     }
     /*th,td*/
     #scrollable2 th, #scrollable2 td{
      width:70px;
      height:50px;
     }
    
     /*border*/
     #scrollable2{
      border:solid 1px black;
     }
     #scrollable2>thead>tr>th{
      border:solid 1px red;
     }
     #scrollable2>tbody>tr>td{
      border:solid 1px blue;
     }
     #scrollable2>tfoot>tr>td{
      border:solid 1px green;
     }
    
    </style>
    <table id="scrollable2" cellspacing="0" cellpadding="0">
     <thead>
      <tr><th class="c1">1</th><th class="c2">2</th><th class="c3">3</th><th class="c4">4</th><th class="c5">5</th></tr>
     </thead>
     <tfoot>
      <tr><td class="c1">1</td><td class="c2">2</td><td class="c3">3</td><td class="c4">4</td><td class="c5">5</td></tr>
     </tfoot>
     <tbody>
      <tr><td class="c1">1</td><td class="c2">2</td><td class="c3">3</td><td class="c4">4</td><td class="c5">5</td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
      <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td></tr>
     </tbody>
    </table>
    

    3 件のコメント:

    1. IE (IE9) で表示すると、スクロールバーの位置がずれてしまいます。

      返信削除
    2. rowspan が無視されて、うまくいかないようですね。

      返信削除
    3. なるほど,colspanやrowspanとかは食い合わせが悪いでしょうね.
      この方法ではtable要素の規定スタイルの一部を敢えて崩しているため,
      セル結合等のtableスタイルに依存した仕組みが上手く働きません.

      理屈から言えばtableを構成する要素全てのスタイル設定を
      逐一再定義してやれば何とかなるはずですが現実的ではありませんね.
      (セレクタ記述が爆発しそう…)

      返信削除