Tableのヘッダ(thead)を固定して、<tbody>内をスクロールさせる方法

Date:2009.09.11

Author:スタッフM

Category:CSS

Tag:,

Tableのヘッダ(thead)を固定して、<tbody>内をスクロールさせる方法

データ量の多い <table> を扱うとき、<thead>部分だけを固定して <tbody> の部分だけ縦スクロールしたい。
という場面があるかと思います。

今回は、Table のヘッダ固定について、採用したパターンのメモです。

Table の固定にあたって、検索で調べると以下のような手段があるようです。

  1. HTMLだけでなんとかする。(ヘッダを別のtableに分ける…とかそんな感じのもの)
  2. CSSだけでなんとかする。(ヘッダ部分をpositionで固定するとか、tbodyにoverflowかけたりする)
  3. JavaScriptを使ってなんとかする。(SuperTable とか使って)
  4. CSSとJavaScriptを使ってなんとかする。(2 と 3 の合わせ技?)

正しい<table>ダグを維持して、内容(tbody部分)が縦スクロールするのが理想。
ということで、まずはCSSでなんとかするという方法を取ってみることに。

対応させるブラウザはIE6〜IE8、FireFox(Win/Mac)。

まず、こんな<table>を用意します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="scrollTableBox">
<table class="scrollTable">
 <thead>
 <tr>
  <th>ヘッダタイトル1</th>
  <th>ヘッダタイトル2</th>
  <th>余分なセル</th>
 <tr>
 </thead>
 <tbody>
 <tr>
  <td>コンテンツデータ1</td>
  <td>コンテンツデータ2</td>
  <td>余分なセル</td>
 </tr>
 <tr>
  <td>コンテンツデータ3</td>
  <td>コンテンツデータ4</td>
  <td>余分なセル</td>
 </tr>
 </tbody>
</table>
</div>

ここで、スクロールさせたい箇所( <tbody> )に対して、CSSで以下のようにスタイルを指定します。

1
2
3
4
5
6
7
<style type="text/css">
.scrollTable tbody {
overflow: auto;
overflow-x: hidden;
height: 任意の高さpx;
}
</style>
※ overflow-x:hidden は、 <table> の大きさ・ブラウザ環境によって、意図していないのに横スクロールが表示されてしまったときに入れておくと良いです。

この時点で、FireFoxはきちんと <tbody> に対して overflow:auto; が正しく適用されています。

※ ちなみに上記の指定は <tbody> に対してスクロール(overflow: auto;)させているので、<tbody> の中にスクロールバーが表示されているということになります。
<table>の右端に余分な列を加えているのは、<tbody> の右端にスクロールバーが入ることで、最後の列だけがスクロールバー分ほど大きくなってしまうため、これを避けるために余分な列を用意しているのです。
(<table>の列の見た目を絶対に変えたりしたくないときに、回避法として用意するといいです)

FireFoxだけなら上記の設定で充分なのですが、IE6〜IE8までの対応もしておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--[if lt IE 8]>
<style type="text/css">
div.scrollTableBox {
overflow: auto;
height: 400px;
}
div.scrollTableBox table tbody {
overflow: visible;
height: auto;
}
div.scrollTableBox table thead tr {
position: relative;
top: expression(offsetParent.scrollTop-window.scrollTop);
}
div.scrollTableBox table thead tr th {
position: relative;
top: expression(offsetParent.scrollTop-window.scrollTop);
}
</style>
<![endif]-->

IE対応の為にやむなくcssの中で expression を使用しています。

こちらは <table> の外側にある <div> に対して overflow:auto; を指定しています。
このままでは、<div> の中にある <table> そのものがスクロールしてしまいます。
そこで、固定したいヘッダ部分( <thead> )を position と expression を使用して、<div> がスクロールされたとき、スクロールしている分の高さの値を top に設定して、<div> をスクロールしても固定されるようにしています。

これで、IE6とIE7は <tbody> のみスクロールが効くようになります。

※ちなみに、cssに expression を使用するときは外部CSSファイルではなく、<head> 内に書く必要があります。

【2009.11.01加筆】

1
top: expression(offsetParent.scrollTop-window.scrollTop);

について補足します。

1
expression

に記述されている

1
-window.scrollTop

は、table が ブラウザより大きくなった場合の対処になります。

table をブラウザの高さに充分収まるように作成しても、ユーザーの環境によってブラウザが自分の意図しないサイズ(tableよりも小さい)だったという場合もあります。

上記の場合、

1
top: expression(offsetParent.scrollTop);

だと以下のようになります。

top: expression(offsetParent.scrollTop); の場合

ウィンドウのスクロールバーを動かすと、 tbody 自体はスクロールされているのですが、 thead だけは固定されたままになっています。

1
top: expression(offsetParent.scrollTop-window.scrollTop);

の場合は、以下のようになります。

top: expression(offsetParent.scrollTop-window.scrollTop); の場合

ウィンドウのスクロールバーを動かすと、thead は固定されることなく、 table 全体がスクロールされています。

Window幅も固定してしまったうえでスクロールTableを作成するのであれば、

1
-window.scrollTop

の記述は必要ありません。
(2009.11.01加筆 ここまで)

IE8は、expression についてはサポート外となってしまっているので、IE8 対応のために以下のMETAタグを挿入します。

1
<meta http-equiv="X-UA-Compatible" content="IE=emulateIE7">

これで、下位互換(IE7スタンダードモード)になり、expression の指定がIE8でも有効になります。

以上で完了。

はじめ、理想の手段としてCSSだけでなんとかするという方向に向かってましたが、IE対応のために expression を使ったので、最終的にはCSSとJavaScroptでなんとかするということに…。

ちなみに、以上の設定でスクロールが動作しなかったブラウザは、Safari(Mac/Win)、Opera(Win)、Chrome(Win)でした。
逆に、古いFireFox(1.5)は、きちんとスクロールされました。

固定させる Table は、レイアウトが単純なほど対応させやすいと思います。

スクロールさせたい <table> の <th> に colspan や、 rowspan があるとIE側ではヘッダを固定したときに <table> のセルの幅が崩れたりすることがほとんどです。
その時は、<thead> の構造をなるべく複雑にならないようにする工夫も必要になってきます。

【2009.09.30加筆】
Tableスクロールを実装したときのキャプチャ画像です。

スクロールするテーブル(キャプチャ)

スクロールするテーブル(キャプチャ画像)

このテーブルはわりとヘッダ部分が複雑になっていますが、崩れることなく tbody部分だけがスクロールされます。

css / html ともにコードは以下の通り。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<style type="text/css">
div.scroll_table table tbody {
overflow: auto;
height: 130px;
overflow-x: hidden;
}
</style>
<!--[if lt IE 8]>
<style type="text/css">
div.scroll_table {
overflow: auto;
height: 400px;
}
div.scroll_table table tbody {
overflow: visible;
height: auto;
}
div.scroll_table table thead tr {
position: relative;
top: expression(offsetParent.scrollTop-window.scrollTop);
}
div.scroll_table table thead tr th {
position: relative;
top: expression(offsetParent.scrollTop-window.scrollTop);
}
</style>
<![endif]-->
<style type="text/css">
th {
background: #ccc;
}
th, td {
border-left:1px #666 solid;
border-bottom:1px #666 solid;
}
th.th_top {
border-top:1px #666 solid;
}
.dummy {
background:none;
border-bottom:none;
}
</style>

※CSSの注意点としては、 table に border-collapse:collapse; を指定しないこと。指定すると、テーブルが崩れてしまいます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
<div class="scroll_table">
<table cellspacing="0">
<colgroup>
<col style="width:20px">
<col style="width:30px;">
<col style="width:50px;">
<col style="width:50px;">
</colgroup>
<colgroup span="24" style="width:10px;"></colgroup>
<colgroup><col style="width:20px;"></colgroup>
<thead>
<tr>
<th rowspan="4" class="th_top">&nbsp;</th>

<th class="th_top">&nbsp;</th>
<th colspan="2" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>

<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>

<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>

<th colspan="2" rowspan="4" class="th_top">&nbsp;</th>
<th class="dummy" rowspan="4">&nbsp;</th>
</tr>
<tr>
<th>&nbsp;</th>
<th colspan="2">&nbsp;</th>
</tr>
<tr>

<th>&nbsp;</th>
<th>&nbsp;</th>
<th>&nbsp;</th>
</tr>
<tr>
<th colspan="3">&nbsp;</th>
</tr>
</thead>
<tbody>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>

<tr>
<td rowspan="3">&nbsp;</td>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3">&nbsp;</td>
<td rowspan="3" class="dummy">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
</div>

以上のコードをそのまま使えば、上のキャプチャ画像のようなスクロールするテーブルが再現できると思います。

※ただし、 rowspan が 複雑になった場合、IE6などではテーブルが崩れてしまいます。
(FireFoxでは崩れることはありません…)

th の rowspan が複雑だと崩れます

th の rowspan が複雑だと崩れます

IE6対応が前提であれば、複雑な rowspan は避けた方が良いと思われます。
もっとスマートにテーブルスクロールできたらなぁ…。

【2009.10.06 加筆】
上記のソースコードで Table スクロールをIE8に実装したとき、Table の内容が ウィンドウ幅を超えると thead が横スクロールされません。

thead がウィンドウ幅を超えたスクロールテーブル

thead がウィンドウ幅を超えたスクロールテーブル

thead の部分が固定された状態で、tbody部分だけがスクロールされてしまいます。

これは、 thead を

1
position:relative

で固定しており、さらに IEの時は table 外側にある <div> を

1
overflow:auto

にすることでスクロールを実現していることが原因になります。

IE のときのスクロールテーブルの動作

IE のときのスクロールテーブルの動作

サンプル用のソースコードでは、 <table> や <div> に対して width の設定は特にしていませんでした。
そのため、 <thead> の内容が <td> の幅を超えて、<table> 全体がウィンドウ幅より大きくなってしまったとき、IEでは <thead> が横スクロールされずに上記キャプチャ画像のようなおかしな表示になってしまいます。

これを回避するには、

  • <table> の width を指定する
  • <table> の width + 20px した幅を <div> に指定する

この2点を行うことが必要です。

<div> の幅が<table> より若干大きくなっているのは、同じ幅に指定すると、ほんの少しだけ横スクロールが表示されてしまうからです。
そのため、<div> には 20px くらい幅を持たせてあげます。

ちなみに、今回のサンプルはあくまでも 縦スクロール対応 が目的だったので、横スクロールのことは考えてなかったりします…。ごめんなさい。

コメント

  1. sugita says:

    素晴らしいできばえです。
    expressionを使用する事で、複数行タイトルへ簡単に対応できるんですね。
    これをIE8で試して見て、
    タイトルに長い文字を入れて、あえてwindow幅からはみ出すようにすると横スクロールでタイトルが固定されてしまいました。
    との横幅が同じならないようです。
    解決策が分からなかったで、の横幅を過大にすると解決するようなのですが..
    なにか良い方法はありませんか?

    • イノマタ says:

      > sugita さま
      参考にしていただいてありがとうございます!

      ご指摘いただいた window幅 から thead がはみ出したときの対処法についてですが、さきほど記事のほうに加筆させていただきました。

      今回のサンプルでは table と div の width を指定していませんでしたが、これらの width を指定していただければ tbody が横スクロールされることはありません。

      ちなみに、記事にも書かせていただきましたが、このサンプルについては横スクロール対策はできていないのです…。
      申し訳ないです。

  2. k says:

    参考にさせていただきました。

    expression(offsetParent.scrollTop-window.scrollTop)
    の部分は、
    expression(offsetParent.scrollTop)
    ではありませんか?

    少なくとも自分の環境IE6では後者でした。

    • イノマタ says:

      > k さま
      参考にしていただき、ありがとうございます。

      ご指摘いただいた expression についてですが、これは table の height がウィンドウよりも大きく(高く)なった場合の thead の固定位置の不具合を考慮した記述になります。
      記事の expression の記述箇所に加筆させていただきましたので、よろしければご参考くださいませ。

この記事へコメントを投稿する

※コメントはスパム対策の為、承認制となっています。あらかじめご了承ください。

 

トラックバック/ピンバック

  1. [...] Tableのヘッダ(thead)を固定して、 内をスクロールさせる方法 ? 株式会社ジラフィー(Giraffy) :: ソフトウェア開発・ウェブデザイン [...]

トラックバックURL