tableの見出しを固定してスクロールする方法
HTMLの<table>で作成した表の見出し部分だけを固定して、内容部分をスクロールできるようにする方法の備忘録です。
上の見出しを固定
表の上部分の見出しを固定して、内容部分を上下にスクロールする方法です。
見出し1 | 見出し2 | 見出し3 | 見出し4 | 見出し5 | 見出し6 | 見出し7 |
---|---|---|---|---|---|---|
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
サンプルの表示では、overflow: scroll;
をつけた<div>タグで囲うことで、グレーの枠の中でスクロールさせています。<table>のまま使用すると、表示している画面の一番上で見出しが固定されます。
HTML
<table>
<tbody>
<tr>
<th>見出し1</th>
<th>見出し2</th>
<th>見出し3</th>
<th>見出し4</th>
<th>見出し5</th>
<th>見出し6</th>
<th>見出し7</th>
</tr>
<tr>
<td>セル</td>
<td>セル</td>
… 省略 …
<td>セル</td>
<td>セル</td>
</tr>
</tbody>
</table>
1行目の<tr>に、<th>で固定する見出しを入れています。
CSS
table {
width: 100%;
position: relative;
}
th, td {
border: none;
white-space: nowrap;
}
th {
font-weight: bold;
color: #fff;
background: #333;
position: sticky;
top: 0;
left: 0;
z-index: 1;
}
tr:nth-child(odd) td {
background: #f3f5f5;
}
余白やデザインに関わる一部のコードは割愛しています。
親要素となるtableにposition: relative;
を設定して、見出し部分のthにposition: sticky;
を設定することで表示位置を固定します。
見出しの固定位置はtop: 0;
、left: 0;
で表の上部に設定します。さらに、z-index: 1;
を指定して内容部分の上に重ねます。
枠線のあるtableの場合
border
で枠線をつけた<table>の場合、そのままでは見出し部分の線がスクロール時に消えてしまうので、border-collapse: separate;
を指定してセルごとにborder
を設定します。
見出し1 | 見出し2 | 見出し3 | 見出し4 | 見出し5 | 見出し6 | 見出し7 |
---|---|---|---|---|---|---|
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
セル | セル | セル | セル | セル | セル | セル |
CSS
table {
border-collapse: separate;
border-spacing: 0;
width: 100%;
position: relative;
}
th, td {
border-right: 1px solid #333;
border-bottom: 1px solid #333;
white-space: nowrap;
}
tr:first-child th,
tr:first-child td {
border-top: 1px solid #333;
}
th:first-child,
td:first-child {
border-left: 1px solid #333;
}
th {
position: sticky;
top: 0;
left: 0;
z-index: 1;
}
<table>にborder-collapse: separate;
、border-spacing: 0;
を設定して、各セルにborder-right
、border-bottom
で枠線をつけます。さらに:first-child
を活用して外側の該当するセルにborder-top
、border-left
を設定して枠線のある表を作成します。
左の見出しを固定
上下のスクロールと同様に表の左部分の見出しを固定して、内容部分を左右にスクロールできます。
見出し1 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
見出し2 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
見出し3 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
見出し4 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
見出し5 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
HTML
<table>
<tbody>
<tr>
<th>見出し1</th>
<td>セル</td>
<td>セル</td>
…
<td>セル</td>
<td>セル</td>
</tr>
… 省略 …
<tr>
<th>見出し5</th>
<td>セル</td>
<td>セル</td>
…
<td>セル</td>
<td>セル</td>
</tr>
</tbody>
</table>
各行の先頭の<th>を見出しとして固定します。
CSS
table {
width: 100%;
position: relative;
}
th, td {
border: none;
white-space: nowrap;
}
th {
font-weight: bold;
color: #fff;
background: #333;
position: sticky;
top: 0;
left: 0;
z-index: 1;
}
tr:nth-child(odd) td {
background: #f3f5f5;
}
th {
position: sticky;
left: 0;
z-index: 1;
}
左右のスクロールの場合はposition: sticky;
にleft: 0;
だけを指定します。
セルのテキストが意図せぬ位置で改行しないようにwhite-space: nowrap;
を指定するかwidth
で横幅を指定します。
縦横の見出しを固定
縦横の見出しを固定する方法です。縦スクロールの時は上の見出しを固定して、横スクロールの時は左の見出しを固定します。
見出し/行 | 見出し1 | 見出し2 | 見出し3 | 見出し4 | 見出し5 | 見出し6 | 見出し7 | 見出し8 | 見出し9 | 見出し10 | 見出し11 | 見出し12 | 見出し13 | 見出し14 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
行1 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行2 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行3 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行4 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行5 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行6 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行7 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行8 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行9 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行10 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行11 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行12 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行13 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行14 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
行15 | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル | セル |
HTML
<table>
<thead>
<tr>
<th>見出し/行</th>
<th>見出し1</th>
<th>見出し2</th>
<th>見出し3</th>
… 省略 …
</tr>
</thead>
<tbody>
<tr>
<th>行1</th>
<td>セル</td>
<td>セル</td>
…
<td>セル</td>
<td>セル</td>
</tr>
… 省略 …
<tr>
<th>行15</th>
<td>セル</td>
<td>セル</td>
…
<td>セル</td>
<td>セル</td>
</tr>
</tbody>
</table>
上部の見出しは<thead>タグ内の<th>で作成します。横の見出しは<tbody>タグ内の各行の先頭<th>で作成します。
CSS
table {
width: 100%;
position: relative;
}
th, td {
border: none;
white-space: nowrap;
}
th {
font-weight: bold;
color: #fff;
background: #333;
position: sticky;
top: 0;
left: 0;
z-index: 1;
}
tr:nth-child(odd) td {
background: #f3f5f5;
}
thead th {
color: #fff;
background: #333;
position: sticky;
top: 0;
z-index: 1;
}
thead th:first-child {
position: sticky;
top: 0;
left: 0;
z-index: 2;
}
tbody th {
color: #fff;
background: #333;
position: sticky;
left: 0;
z-index: 1;
}
<thead>、<tbody>の各<th>をposition: sticky;
で位置固定します。
さらに、左上のセルがどのスクロールでも動かないようにth:first-child
で固定してz-index: 2;
で一番上に重ねます。