tableを横スクロールさせる際に
一部のヘッダーを固定させて表示する方法

  • 2023.12.29

HTML・CSS系

tableを横スクロールさせる際に一部のヘッダーを固定させて表示する方法

前回にtableを使う際の横スクロールについてまとめました。
その時の注意点として、使い方やセルの中に書かれたコンテンツなどによっては視認性が低くなったりすることもあるので、本当に使うかどうか注意して考えましょう。的なことを書きました。

【CSS】スマホで見る時にtableを横スクロールで表示させる方法とコード

【CSS】スマホで見る時にtableを横スクロールで表示させる方法とコード
サイトの性質などによっては、テーブルを多用するサイトなどを作る機会があります。昔のようにPCだけの閲覧を考えている時代であれば問題ないのですが、最近で...

今回の件はそれらを解決するための1つの方法で、テーブルを横スクロールさせるときに一番左のセルを固定しながらスクロールさせることができるようになります。

これを使えば、縦長になってしまうテーブルでもスクロールした際に一番上や一番左を固定したまま表示ができるので、そのまま横スクロールさせて表示するよりも一層見やすくなります。

今回はそんなテーブルを横スクロールさせる際に一部のヘッダーを固定表示させる方法について見ていきたいと思います。

まずはデモでどういう見え方かの確認

まずは同じテーブルをヘッダーを固定させて表示させるものと、させずに表示してどう違うかを実際にtableを表示して確認してみましょう。

固定させずに表示させる

前回のタグをほとんどそのまま使い回しています。

THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

固定させて表示

最初のthのヘッダー部を固定して表示すると下記になります。

THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

このように、ヘッダーを固定して表示することでテーブルの見え方が変わるため表示内容などによってはこちらを使う事ではるかに見やすいテーブルに仕上げる事ができます。

実際のコードについて

それでは実際のコード各種を見ていきましょう。
基本的にコードは前回のテーブルのものをベースとして使っています。

HTMLのコード

HTMLのコードはほとんど変わりません。
唯一変わっているのは、固定化したい部分にクラス名を与えています。

<div class="table-scroll">
  <table>
    <tr>
      <th class="sticky">THの見出し</th>
      <td>テキストテキスト</td>
      <td>テキストテキストテキストテキスト</td>
      <td>テキストテキストテキストテキストテキストテキストテキストテキスト</td>
    </tr>
    <tr>
      <th class="sticky">THの見出し</th>
      <td>テキストテキスト</td>
      <td>テキストテキストテキストテキスト</td>
      <td>テキストテキストテキストテキストテキストテキストテキストテキスト</td>
    </tr>
    <tr>
      <th class="sticky">THの見出し</th>
      <td>テキストテキスト</td>
      <td>テキストテキストテキストテキスト</td>
      <td>テキストテキストテキストテキストテキストテキストテキストテキスト</td>
    </tr>
    <tr>
      <th class="sticky">THの見出し</th>
      <td>テキストテキスト</td>
      <td>テキストテキストテキストテキスト</td>
      <td>テキストテキストテキストテキストテキストテキストテキストテキスト</td>
    </tr>
    <tr>
      <th class="sticky">THの見出し</th>
      <td>テキストテキスト</td>
      <td>テキストテキストテキストテキスト</td>
      <td>テキストテキストテキストテキストテキストテキストテキストテキスト</td>
    </tr>
 </table>
</div>

CSSのコード

一方でCSSはかなり大幅に変わります。

.table-scroll {
  overflow-x: auto;
}

.table-scroll table {
  width: 100%;
  min-width: 1000px;
  table-layout: fixed;
  margin-bottom: 1px;
  border-collapse: collapse;
}

.table-scroll th,
.table-scroll td {
  width: 200px;
  padding: 15px;
  border: 1px #ccc solid;
}

.table-scroll th.sticky{
  position: sticky;
  top:0;
  left:0;
  border-left: none;
  border-right: none;
  background: none;
}

.table-scroll th.sticky::before{
  content: "";
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  border-left: 1px #ccc solid;
  border-right: 1px #ccc solid;
  background-color: #eee;
  z-index: -1;
  box-sizing: content-box;
}

装飾的な要素も含まれていますが、上記のデモで使っているコードとしてはこのような形になっています。実際に、それぞれ見て言ってみましょう。

それぞれのコードの解説

HTMLは固定したいところにクラス名を与えるだけなので割愛します。大切になってくるのがCSSになりますので、そちらを見ていきましょう。

tableとその大枠は前回のままです。
特にこれといって変わったところはありませんし、難しいところもありません。

固定化するところの設定

.table-scroll th.sticky{
  position: sticky;
  top: 0;
  left: 0;
  border-left: none;
  border-right: none;
  background: none;
}

変わったところはここですね。
HTMLでクラス名を与えた、.stickyの固定するところの設定になります。

まずposition: sticky;これで固定しています。
位置を左上のために、topleftにそれぞれ0としています。

そして大切なところの1つが、borderbackgroundです。
この2つはいったんnoneとして打ち消していますが、これはstickyを設定したとしても、ボーダーや背景色というのは固定されないのです。

そのため、ここで横スクロールする際に影響が出てしまう左右のボーダーを無しに上書き設定してから、次の疑似要素の::beforeにてボーダーと背景色を再設定しているという形を取っています。

これをしない場合、下記のサンプルのように固定化したときにボーダーが1pxだけズレてしまったり背景色でボーダーが打ち消しされたりしてしまいます。下記のデモ・サンプルは、.stickyの中身をこのようにしたものになります。

.table-scroll th.sticky{
  position: sticky;
  top: 0;
  left: 0;
 }

実際に見ると背景色でボーダーが重なって消えてしまったり、スクロールするとボーダーがおかしいのがわかるかと思います。そうならないための左右のボーダーと背景色を再設定で無しにしています。

THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

疑似要素で枠線や背景を設定

.table-scroll th.sticky::before{
  content: "";
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  border-left: 1px #ccc solid;
  border-right: 1px #ccc solid;
  background-color: #eee;
  z-index: -1;
  box-sizing: content-box;
}

ここの部分ですね。
先ほども書いたように、.stickyを使った場合は背景色やボーダーが特殊なため、疑似要素で行わないとスクロールした時にズレが起こってしまいます。

そのため、position: absolute;で絶対配置として場所を左上に指定し横も縦も100%という表示にしています。その上で、設定したかったスクロールする横線をここで指定しています。

そして大事なのが最後の2つです。
まず、z-index: -1;ですが、これはあくまでも枠線と背景色を設定した要素になるため、絶対配置で指定しているため、前面に出てしまうとthの中がこの背景色で埋め尽くされてしまう事になります。

そうならないために、-1を指定して、1つ後ろ側に回るように設定をしています。

そして最後のbox-sizing: content-box;ですが、多くの場合、デフォルトCSSなどで、border-boxとしいて指定していることが多いのではないかなと思います。

しかしながら、border-boxのままだと固定化するthとその最初のtdの枠線が二重に表示されてしまうことになります。そうならないためにcontent-boxを指定すると綺麗に表示され意図している綺麗な表示がなされるのです。

この設定で、実際に先ほど上記でも書いていた見出し部分を固定した綺麗なスクロールのテーブルが出来上がるわけです。

THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
THの見出しテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト

横スクロールがうまく動かない時のチェックポイント

最後に、この横スクロールが動かない、もしくは動くけど意図した動き(ボーダーや背景など)になっていないという時のチェックポイントを挙げておきます。

  • tableにborder-collapse: collapse;が入っているか
  • stickyを指定したところで、ボーダーと背景の打ち消しを入れているか
  • 疑似要素でボーダーと背景を再設定しているか
  • 疑似要素のところで、z-index: -1;を設定し忘れてないか
  • box-sizingで、content-boxを指定しているか

だいたいこのあたりの漏れで、意図してない動きになることが多いのではないかなと思います。

まとめ

テーブルの横スクロール時に一部を固定して表示する方法をまとめてみました。実際に横スクロールのテーブルを使う際にはこの機能を使うことは多いかなと思います。

これがあるかないかで、見る側からすると何度もテーブルの左右を行き来しなくて済むことに繋がるので是非使い方を覚えて、必要な時に使えるようになっておくと良いと思います。

ただ実際に使おうとすると、細かいところまで見ていくと1pxのボーダーのズレだったりなどがよく発生したりするので、ズレが起きないように構築できるようになっておくと尚良いと言えると思います。

記事のシェアにご協力お願いします

この記事と類似テーマの記事