
・tableタグのヘッダーを固定スクロールする方法ある?
こんな疑問にお答えします。
tableを使って横スクロールするときに、見出しのヘッダーだけ固定させたい時ありますよね。
こんな感じで↓

実はこれ、簡単に実装できちゃいます。

すぐにできるよ!
ということで、この記事では「tableタグのヘッダーを固定してスクロールする方法」について解説していきます!
ちなみに横スクロールする方法に関しては、
下記で解説してるので参考に↓

・【列】tableタグのヘッダーを固定してスクロールする方法
・【行】tableタグのヘッダーを固定してスクロールする方法
・【列+行】tableタグのヘッダーを固定してスクロールする方法
目次
【簡単】tableタグのヘッダー列を固定してスクロールする方法【HTML/CSS】
まずはサンプルをご覧ください↓
See the Pen Untitled by jito-coder (@jito-coder) on CodePen.
<div class="table-sticky">
<table class="table-sticky__container">
<tr>
<th class="table-sticky__title">見出しタイトル</th>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
</tr>
<tr>
<th class="table-sticky__title">見出しタイトル</th>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
</tr>
<tr>
<th class="table-sticky__title">見出しタイトル</th>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
</tr>
</table>
</div>
.table-sticky {
overflow-x: auto;
max-width: 100%;
width: 500px;
margin-top: 30px;
margin-right: auto;
margin-left: auto;
}
.table-sticky__container {
width: 1000px;
border-collapse: collapse;
border-spacing: 0;
}
th {
width: 250px;
padding: 25px;
color: #000066;
border: 1px solid #000066;
background-color: red;
}
td {
width: 200px;
padding: 25px;
border: 1px solid #000066;
}
.table-sticky__title {
position: sticky;
top: 0;
left: 0;
}
.table-sticky__title::before{
content: "";
position: absolute;
top: -1px;
left: -1px;
width: 100%;
height: 100%;
border: 1px solid #000066;
}
左の赤背景部分だけ固定されて、横スクロールできるようになっていますよね!
コードとして重要な部分はこちら↓
- 見出しを「position: sticky;」で固定
- 見出しの背景色を指定する
- 見出しに疑似要素でborderを作成
順に解説していきます!
まず固定したい部分に「position: sticky;」を指定します。これをすることで、指定された場所まで行くと固定されるようにできます。
今回でいうと下記コードですね↓
<th class="table-sticky__title">見出しタイトル</th>
.table-sticky__title {
position: sticky;
top: 0;
left: 0;
}
これで見出しタイトル部分を、固定させることできました。
次に固定させた見出しに、背景色を指定します。背景色を指定しないと、重なる文章や要素がそのまま映るため。
背景色がないと下記みたいになっちゃいます↓

これの対策として、背景色を指定しましょう。
今回のコードでいうとこちら↓
th {
~~~
background-color: red;
}
最後に固定させる見出しに対して、疑似要素を指定してborderを作成します。というのも「position:sticky」だけだと、borderまで固定することができないんですよね。
つまり本来なら下記みたいになってしまう↓

見出し部分の左右borderが、スクロールしたら消えてますよね。
そのため疑似要素で新たにborderを作成します。
今回でいうと下記コードですね↓
.table-sticky__title::before{
content: "";
position: absolute;
top: -1px;
left: -1px;
width: 100%;
height: 100%;
border: 1px solid #000066;
}
初めて僕がこの実装をした時、borderの位置がおかしく沼にハマりました。。
で、色々調べた結果「box-sizing: border-box;」が原因だとわかりました。。これを指定してると、borderの位置がずれてしまいます。

初歩的なミス。。
「box-sizing: content-box;」を疑似要素に対してつけたら治りました!
下記みたいに↓
.table-sticky__title::before{
~~~
box-sizing: content-box;
}
【簡単】tableタグのヘッダー行を固定してスクロールする方法【HTML/CSS】
続いて「行」の見出しを固定してスクロールさせる方法を紹介していきます!
サンプルがこちら↓
See the Pen Untitled by jito-coder (@jito-coder) on CodePen.
<div class="table-sticky2">
<table class="table-sticky2__container">
<tr>
<th class="table-sticky2__title">見出しタイトル</th>
<th class="table-sticky2__title">見出しタイトル</th>
<th class="table-sticky2__title">見出しタイトル</th>
</tr>
<tr>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
</tr>
</table>
</div>
.table-sticky2 {
overflow-y: auto;
height: 250px;
}
といっても、根本的なやり方は列の時と同じ。
thを記載する場所と、tableの縦の長さを指定+overflow-y: auto;を変更するだけですね!
【簡単】tableタグのヘッダー「列+行」を固定してスクロールする方法【HTML/CSS】
最後に列+行の見出しを固定させた、tableタグを紹介していきます!
サンプルがこちら↓
See the Pen ➁tableタグのヘッダー by jito-coder (@jito-coder) on CodePen.
<div class="table-sticky3">
<table class="table-sticky3__container">
<tr>
<th class="table-sticky3__title table-sticky3__title01">見出しタイトル</th>
<th class="table-sticky3__title table-sticky3__title02">見出しタイトル</th>
<th class="table-sticky3__title table-sticky3__title02">見出しタイトル</th>
<th class="table-sticky3__title table-sticky3__title02">見出しタイトル</th>
</tr>
<tr>
<th class="table-sticky3__title table-sticky3__title02">見出しタイトル</th>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
</tr>
<tr>
<th class="table-sticky3__title table-sticky3__title02">見出しタイトル</th>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
<td>ここにテキストが入ります。ここにテキストが入ります。</td>
</tr>
</table>
</div>
.table-sticky3__title01 {
z-index: 2;
}
.table-sticky3__title02 {
z-index: 1;
}
重要な点は、固定される見出しの重ね順ですね。
一番左上の見出しタイトルだけ「z-index: 2;」としています。これにより横スクロールしても、縦スクロールしても良い感じに反映が可能に。
【簡単】tableタグのヘッダーを固定してスクロールする方法【HTML/CSS】:まとめ
- 見出しを「position: sticky;」で固定
- 見出しの背景色を指定する
- 見出しに疑似要素でborderを作成
- 「列+行」⇒固定される見出しの重ね順を変更

tableタグのヘッダーを固定させる実装はよくあるので、覚えておこう!