【CSS】 表の項目名(ヘッダー)をスクロールに追従させる方法

この記事は約9分で読めます。
記事内に広告が含まれています

コーディングのイメージ

こんにちは、さち です。

サイトを作る時に「表 <table>」を使うことがあるんですが、行数が多いときはスクロールをしても見やすくするために「ヘッダー(項目名) <th>」を常に表示しておきたいことがあります。

そんな時に役立つのが、CSS の position: sticky; です。

ただ、ちゃんと実装しようとすると、意外と面倒な仕様が多かったので、備忘録も兼ねて position: sticky; の使い方を書いていきます。

スポンサーリンク

表の項目名を固定する

サンプル

サンプルとして作った表がこちら。表をスクロールしても、ヘッダー(項目名)の「名前」「身長」が追従して常に表示されていますね。

名前 身長[cm]
朝香 果林 167
エマ・ヴェルデ 166
鐘 嵐珠 165
宮下 愛 163
三船 栞子 160
上原 歩夢 159
近江 彼方 158
桜坂 しずく 157
高咲 侑 156
ミア・テイラー 156
中須 かすみ 155
優木 せつ菜 154
天王寺 璃奈 149

HTML

<div class="scroll">
  <table>
    <tr class="sticky"><th>名前</th><th>身長[cm]</th></tr>
    <tr><td>朝香 果林</td><td>167</td></tr>
    <tr><td>エマ・ヴェルデ</td><td>166</td></tr>
    <tr><td>鐘 嵐珠</td><td>165</td></tr>
    <tr><td>宮下 愛</td><td>163</td></tr>
    <tr><td>三船 栞子</td><td>160</td></tr>
    <tr><td>上原 歩夢</td><td>159</td></tr>
    <tr><td>近江 彼方</td><td>158</td></tr>
    <tr><td>桜坂 しずく</td><td>157</td></tr>
    <tr><td>高咲 侑</td><td>156</td></tr>
    <tr><td>ミア・テイラー</td><td>156</td></tr>
    <tr><td>中須 かすみ</td><td>155</td></tr>
    <tr><td>優木 せつ菜</td><td>154</td></tr>
    <tr><td>天王寺 璃奈</td><td>149</td></tr>
  </table>
</div>

<table><div> で囲んでスクロールさせています。

スクロール時に追従させたいヘッダーの <tr>class="sticky" を追加してあります。

CSS

.scroll {
  height: 250px;
  overflow-y: scroll;
}

.sticky {
  position: sticky;
  top: 0;
  z-index: 1;
}

ヘッダーを追従させるために、クラス stickyposition: sticky; を記述。

また、top: 0; によって追従時に固定する位置を指定しています。今回の場合は、スクロール時にトップ(上端)で固定されます。(もちろん、bottom left right などでもOK)

さらに、z-index: 1; でヘッダーが他の要素よりも上に重なるように調整しています。(値は状況に合わせて変更して下さい)

ちゃんと実装するためのコツ

position: sticky; を付けるだけでは、ちゃんと動かないことがありました。気をつけないといけないポイントを書いていきます。

【注意1】 「border-collapse」の値

表のセルを線(罫線)で区切る場合は、CSS で border-collapse: collapse; を設定していると、position: sticky; が付いている要素の罫線が消えてしまいます

この問題の対処法は、次の2つのどちらかです。

対処法
  • 罫線で区切るデザインをやめる
  • border-collapse の値を separate に変える

ちなみに、border-collapse: separate; にすると、この設定の性質上、セルを区切る罫線のデザインが変わってしまいます。

この状態で 1px の罫線でセルを区切るには、各セルに対して「上・下」「左・右」ぞれぞれどちらか一方にだけ border を設定するようにします。

【注意2】 「overflow」の値

今回の例のように、小さい要素の高さでスクロールさせる場合は問題ありません。

しかし、大きな表でブラウザー自体のページスクロールに追従させたい場合は、親要素(祖先要素)に設定する overflow の値を visible にしないと上手くいきません。

ちなみに、overflow の初期値は visible なので自分で変えていない限り大丈夫ですが、問題の原因になる設定だと気付きにくいのが落とし穴です。

【おまけ】 比較対象を常に表示する

サンプル

position: sticky; を使って、特定の「行」のデータを常に表示させています。

名前 身長[cm]
朝香 果林 167
エマ・ヴェルデ 166
鐘 嵐珠 165
宮下 愛 163
三船 栞子 160
上原 歩夢 159
近江 彼方 158
桜坂 しずく 157
高咲 侑 156
ミア・テイラー 156
中須 かすみ 155
優木 せつ菜 154
天王寺 璃奈 149

HTML

<div class="scroll">
  <table>
    <tr class="sticky"><th>名前</th><th>身長[cm]</th></tr>
    <tr><td>朝香 果林</td><td>167</td></tr>
    <tr><td>エマ・ヴェルデ</td><td>166</td></tr>
    <tr><td>鐘 嵐珠</td><td>165</td></tr>
    <tr><td>宮下 愛</td><td>163</td></tr>
    <tr><td>三船 栞子</td><td>160</td></tr>
    <tr><td>上原 歩夢</td><td>159</td></tr>
    <tr class="sticky-row"><td>近江 彼方</td><td>158</td></tr>
    <tr><td>桜坂 しずく</td><td>157</td></tr>
    <tr><td>高咲 侑</td><td>156</td></tr>
    <tr><td>ミア・テイラー</td><td>156</td></tr>
    <tr><td>中須 かすみ</td><td>155</td></tr>
    <tr><td>優木 せつ菜</td><td>154</td></tr>
    <tr><td>天王寺 璃奈</td><td>149</td></tr>
  </table>
</div>

ヘッダーに以外に、データの <tr> には class="sticky-row" を追加してあります。

CSS

.scroll {
  height: 250px;
  overflow-y: scroll;
}

.sticky {
  position: sticky;
  top: 0;
  z-index: 1;
}

.sticky-row {
  position: sticky;
  top: 44px;
  bottom: 0;
  z-index: 1;
}

クラス sticky-rowposition: sticky; を記述して追従させます。

top: 44px; によって上端から 44px の位置で固定されますが、bottom: 0; によって下端の位置でも固定されます。

さらに、z-index: 1; で他の要素よりも上に重なるように調整しています。(値は状況に合わせて変更して下さい)

コメント

タイトルとURLをコピーしました