こんにちは、さち です。
サイトを作る時に「表 <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; }
ヘッダーを追従させるために、クラス sticky
に position: 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-row
に position: sticky;
を記述して追従させます。
top: 44px;
によって上端から 44px の位置で固定されますが、bottom: 0;
によって下端の位置でも固定されます。
さらに、z-index: 1;
で他の要素よりも上に重なるように調整しています。(値は状況に合わせて変更して下さい)
コメント