2012年2月13日月曜日

続・複雑なレイアウトのテーブルを実装する際のヒント


前回はcss3に対応したブラウザfirefox,chrome,opera等で複雑なレイアウトのテーブルを実現する方法を探ったが,どうやらもっといいやり方が見つかったので公開してみる.今回はie8でも同じレイアウトとなるので汎用性が高いと思う.

かいつまんで言うとtable要素にdisplay:blockやfloat:left等を指定すると,それまでの表組みの縛りから解放されるので,table要素群の構造をそのままに自由なスタイル指定が可能となるということ.例えばtbody要素にoverflow:autoを指定すれば容易にヘッダー・フッター固定のレイアウトを実現することが可能となる等自由自在.


通常複雑なテーブルを実装する場合,いつもはrowspanやcolspan等を使ってセルを結合させて見栄えを良くするのが通例だった.でもよく考えると,セルの結合ってものは単なる見た目のために行う操作であって,元来tableタグのもつ表…データの行列配置といったものとは切り分けて考えたいというのが自然だろう.つまり見た目はcssで制御するのが筋だ.

ではどのようにすればレイアウトの操作が可能となるのか?前回はdisplay:blockにて対処したが,実はもっと簡単な方法があった.td,th要素にfloat:leftを指定するだけで良かったのだ.下記に例を示す.


適切にwidthとheightを設定し,float:leftにてセルを左詰めにしてしまうのだ.こうすることで自由に行のレイアウトを設定することが可能となる.上下に分割したくないセルはfloat無指定とする.
前回と異なり,tbodyとtfootが本来の順序で記述されているし,何よりvertical-alignも正しく動作している点に注意して欲しいよーく見るとfloatが効いている要素はvartical-alignが殺されているようだ.

逆に気がついた範囲で注意すべき点を並べてみる.要はわざわざブラウザ側で体裁よく配置してくれているのを自ら崩しているわけだから,動作確認は自己責任ってことです.
  • 余りに構成が複雑でfloatでの制御が出来ない場合は諦める.→素直にcolspan,rowspan属性で対応,もしくはdisplay:block+position:absoluteで切り抜ける.
  • テーブルのセルは可変幅であるので,内容が膨らんだ際レイアウトが崩れてしまう.(floatによる制御が崩れる)
  •  border,cellspacing,cellpadding,border-collapse等の不確定要素が多分に含まれている.→思わぬところでレイアウトの崩壊につながることも.
  • 列固定の処理とは相性が良くない.display:blockを指定したセルとfloat:leftを指定したセルが干渉して制御しにくい.
対応するブラウザはfirefox,chrome,opera,IE8(ie9は未調査…)と広範な環境で動作する.なおie6,7においてはfloat自体が無視され,単なる表形式でレンダリングされるので,データの表示上のデメリットは少ない.

table×floatで遊んでみた.


<!DOCTYPE html>
<html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
 <style type="text/css">
  /*テーブル幅を固定する(こうしないとズレる)*/
  table{
   border:solid 1px black;
   width:252px;
  }
  thead th{
   border:solid 1px red;
  }
  tbody td{
   border:solid 1px green;
  }
  tfoot td{
   border:solid 1px blue;
  }
  td, th{
   font-size:8px;
   padding:0;
  }
  /*ie8のためにカラム毎にクラスを設定している.nth-child(n)と同等*/
  th.c1, td.c1{
   width: 8px;
   height: 28px;
  }
  th.c2, td.c2{
   width: 48px;
   height: 13px;
   float: left;
  }
  th.c3, td.c3{
   width: 48px;
   height: 13px;
   float: left;
  }
  th.c4, td.c4{
   width: 58px;
   height: 28px;
  }
  th.c5, td.c5{
   width: 128px;
   height: 8px;
   float: left;
  }
  th.c6, td.c6{
   width: 128px;
   height: 8px;
   float: left;
  }
  th.c7, td.c7{
   width: 63px;
   height: 8px;
   float: left;
  }
  th.c8, td.c8{
   width: 63px;
   height: 8px;
   float: left;
  }
 </style>
 </head>
 <body>
  <table 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><th class="c6">6</th><th class="c7">7</th><th class="c8">8</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><td class="c6">6</td><td class="c7">7</td><td class="c8">8</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><td class="c6">6</td><td class="c7">7</td><td class="c8">8</td></tr>
 <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td><td class="c6"></td><td class="c7"></td><td class="c8"></td></tr>
 <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td><td class="c6"></td><td class="c7"></td><td class="c8"></td></tr>
 <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td><td class="c6"></td><td class="c7"></td><td class="c8"></td></tr>
 <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td><td class="c6"></td><td class="c7"></td><td class="c8"></td></tr>
 <tr><td class="c1"></td><td class="c2"></td><td class="c3"></td><td class="c4"></td><td class="c5"></td><td class="c6"></td><td class="c7"></td><td class="c8"></td></tr>
   </tbody>
  </table>
 </body>
</html>




ちょっと古い資料だ けれど,tableの仕組みについてざっと目を通すと,このレイアウトがあながち間違いじゃないことが判る.そうなんだよ.表なんてものはデータ表現上の概念 なんだから,それをどう体裁よく画面に表示するかって点で制限があったらおかしいんだよ.見た目に引きずられてtable要素が爆発するってのは本末転倒なんだよ.と腑に落ちた.
だとしたら,colspanとかrowspanとか何の意味があるのよ?って事になるわけだが,これは意味的に複数のデータ行に跨った情報をまとめて表現したい際に用いるべきで,そもそもレイアウト用途で策定されたものではないんだろうなぁ.

0 件のコメント:

コメントを投稿