ヘッダ固定テーブルの最良解 Pushpin Header

HTMLで、ヘッダを固定してボディを縦方向にスクロール可能にしたテーブルを作る方法はいろいろあって、テーブル ヘッダ固定ぐぐると百花繚乱、群雄割拠という感じだけれども、個人的には http://codylindley.com/CSS/249/pushspin-header-a-simplified-data-grid-with-a-stationary-header に載っていた方法が

  • HTML+CSSのみで動作。JavaScript不要
  • IE6, IE7, IE8でも動作*1
  • tableタグとその中身は全く普通の構造。tableの分割もしない
  • 「ヘッダ部分だけを、CSSの絶対位置指定で無理矢理スクロール領域の外に固定する」と一行で説明できる単純で理解しやすい動作原理

と、ベストだと思う。

ところが、最近上記ページを見直してみたらなんか消えていて確認できなくなっていたので*2、記憶をたよりにやり方を再確認しておく。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>Pushpin Header test</title>
<style type="text/css">

body, table {
  font-size: 12px;
}

/* ---------- キモになる部分+枠線 ---------- */

/* 全体の枠。ヘッダが入る分だけ上部を空けておく */
.container {
  position: relative;
  padding-top: 20px;
  border: 1px solid red;
}

/* .container からヘッダのスペースを除いた部分。ここがスクロール対象 */
.content {
  overflow: auto;
}

.scrollable {
  border-collapse: collapse;
}

/* ヘッダ部分。位置を .container の左上端に移動 */
.scrollable thead tr {
  position: absolute;
  top: 0;
  left: 0;
}

/* このheightと .container の padding-top を合わせる */
.scrollable thead th {
  height: 20px;
  border-color: blue;
  border-style: solid;
  border-width: 0px 1px 1px 0px;
}

.scrollable tbody td {
  height: 20px;
  border-color: black;
  border-style: solid;
  border-width: 1px 1px 0px 0px;
}

/* ---------- 表ごとに異なる値はclassを分ける ---------- */

.container1 {
  width: 200px;
}

.content1 {
  width: 200px;
  height: 80px;
}

/* 各カラムにはwidth を設定する必要がある */
.table1 th, .table1 td {
  padding: 0 3px 0 3px;
  width: 80px;
}

.table1 th {
  background-color: #ccc;
}
</style>
</head>
<body>

<!-- 全体枠 -->
<div class="container container1">
<!-- スクロール領域 -->
<div class="content content1">
<table class="scrollable table1">
<thead>
  <tr><th>head1</th><th>head2</th></tr> 
</thead>
<tbody>
  <tr><td>body1</td><td>body2</td></tr>
  <tr><td>body1</td><td>body2</td></tr>
  <tr><td>body1</td><td>body2</td></tr>
  <tr><td>body1</td><td>body2</td></tr>
  <tr><td>body1</td><td>body2</td></tr>
</tbody>
</table>
</div>
</div>

</body>
</html>
  • IEでは、DOCTYPE等を書いて標準準拠モードで動かす必要あり
  • 細かい幅や枠線の調整ではIE/Firefox等で違いが出る場合あり。ただしこの手法自体とは関係ないCSSの一般的な問題なので自分で頑張る

*1:上記のサンプル自体はIE6, IE7では未確認。ただ、以前同様の方法を採ったときはIE6, IE7でも動作を確認したので、微調整すれば使えるはず。

*2:ブログ記事抜きの実例だけは http://codylindley.com/blogstuff/css/pushpin/pushpin.html に残っているっぽい。