atsukanrockのブログ

Microsoft系技術を中心にぼちぼち更新します

ヘッダ固定テーブルをCSSで実装してはいけない

はじめに

企業向けシステムでは、ヘッダ固定テーブルの実装を要求されることがある。ヘッダ固定テーブルとは、

  • テーブル(<table>タグ)である
  • テーブルの横に、テーブル部分のみのスクロールバーが表示される
  • テーブル部分のみのスクロールバーでスクロールしても、テーブルのヘッダ行はスクロールしない

といった特徴を持つもので、いわばExcelの[ウィンドウ枠の固定]機能のWebアプリ版だ。

CSSで実装するには

Pushpin Headerと呼ばれるテクニックがある。positionプロパティを巧みに使った華麗なテクニックだ。ちなみに私は、このテクニックを初めて見たときは理解できなかった。positionプロパティについての正確な知識がないと、理解は難しい。

Pushpin Headerテクニックの問題点

上記リンク先のページをSafari*1で表示すると、ヘッダとボディの間にスペースが空いてしまう。この問題については、テクニックの解説でも記述されている。

Safariでのスペース問題の回避策

今のところ、この問題を回避するにはCSSハックしか手段がないと思われる。なので、Safariのみに適用されるようなCSSハックを探すことになる。

CSSハックを探すが…

私はそれを試みたが、インターネット上のCSSハックについてのページの間違いの多さに唖然とした。なぜそれほどに間違いが多いのだろうか。

CSSハックの問題点

それは、CSSハックの持つ性格によると思う。CSSハックはブラウザのバグを利用したテクニックである。バグなのだから、いつ修正されるかわからない。インターネットでCSSハックを紹介しているページの作成者は、ページ作成時には実際にブラウザで表示して動作を確認しているだろう。それが、時間の経過とともにブラウザのバージョンが上がり*2CSSハックが期待通りに動作しなくなるのだ。

CSSでの実装に対する結論

  • ヘッダ固定テーブルをPushpin Headerテクニックで実装
  • 対応ブラウザにSafariが含まれている

を同時に満たそうとすると、CSSハックの使用を余儀なくされる。しかし、CSSハックの性格は上記のとおりなので、時間の経過とともにシステム修正を迫られる可能性が高まっていく。企業向けシステムでは、いったんリリースしたものはできるだけ修正したくない。
システムの対応ブラウザのバージョンを、「IE 6.0以上」などではなく「IE 6.0.xxxx.xxxx.〜限定」などとできればよいのだが、そんな過保護な動作環境定義はまずない。
よって、システムの対応ブラウザを限定できない場合は、CSSでの実装は諦めた方が良い。

でも実装しなければならない…

CSSでの実装を諦めた場合、どうやって実装すればよいのか。簡単だ。ヘッダとボディを別テーブルとすれば良い。Web標準に反することは間違いない*3。しかし、納期のある仕事としてシステム開発をしているのだから、割り切りも必要だと私は思う。

テーブル分割での実装サンプル

以下のようなコードとなる。

<table style="width: 150px;">
    <tr>
        <th style="width: 50px;">ほげ</th>
        <th style="width: 100px;">ふが</th>
    </tr>
</table>
<div style="height: 100px; overflow: auto; width: 167px;">
    <table style="width: 150px;">
        <tr>
            <td style="width: 50px;">ほげ1</td>
            <td style="width: 100px;">ふが1</td>
        </tr>
        <tr>
            <td style="width: 50px;">ほげ2</td>
            <td style="width: 100px;">ふが2</td>
        </tr>
        <tr>
            <td style="width: 50px;">ほげ3</td>
            <td style="width: 100px;">ふが3</td>
        </tr>
        <tr>
            <td style="width: 50px;">ほげ4</td>
            <td style="width: 100px;">ふが4</td>
        </tr>
        <tr>
            <td style="width: 50px;">ほげ5</td>
            <td style="width: 100px;">ふが5</td>
        </tr>
    </table>
</div>

このコードサンプルはあくまでイメージであり、実際には

  • classでスタイル指定する
  • 2つのテーブル全体を囲む要素との位置関係を適切に指定する

などとしなければならない。
このコードサンプルのポイントは

  • テーブルセルのwidthを明示的に指定している
  • ボディ部のテーブルを囲むdivに対し、heightを指定してoverflow: autoを指定している

といった点だ。

*1:Win XP上のSafari 3.1、Mac OS X Tiger上のSafari 2.0.3で確認した

*2:マイナーバージョンかもしれないし、ビルドバージョンかもしれない

*3:実際にWeb標準を確認したわけではないが