Help us understand the problem. What is going on with this article?

CSSのみで行・列ヘッダ固定テーブルを実装(Firefox / Chrome / Safari)

More than 1 year has passed since last update.

Introduction

モダンブラウザにおいてposition: stickywidth: max-contentの対応が進んだことで、CSSのみで行・列ヘッダ固定テーブルを容易に実装できるようになりました。

なお、各ブラウザの対応状況が異なるため、現状ではセルの横幅(場合によっては高さも)を明示する課題を残してはいますが、保守性は大幅に向上されました。

Goal

20170907-225500_capture.gif

StickyTable | CodePen

Support

本実装での各ブラウザの対応状況です。

ブラウザ バージョン 対応状況
Chrome v.60
Firefox v.55
Safari v.10.1
Edge v.15 ×

How to

HTML

<table class="sticky_table">
  <thead>
    <tr>
      <th class="blank">&nbsp;</th>
      <th>head</th>
      <th>head</th>
      <!-- ... -->
    </tr>
    <!-- ... -->
  </thead>
  <tbody>
    <tr>
      <th>left</th>
      <td>data</td>
      <td>data</td>
      <!-- ... -->
    </tr>
    <!-- ... -->
  </tbody>
</table>

HTMLはシンプルなテーブルの記述です。
ヘッダ固定テーブルを実装するために以下を行います。

  • tableタグにsticky_tableクラスを付与する。
  • theadのtrの1列目(固定列と固定行の交差部分)にblankクラスを付与する。

CSS

tableタグ

.sticky_table {
  display: block;
  position: relative;
  overflow: scroll;
  width: calc(100vw - 3.0rem);
  height: calc(75vh);
  border-collapse: collapse;
  font-size: 0;
}

tableタグは幅と高さを決め、子要素がはみ出した際にスクロールするようにします。

position: relativeは、子要素の位置が相対指定となった際の基準として明記します。

font-size: 0は後述のinline-block要素を横並びにした際に生じる隙間を回避するために指定します。

thead, tbodyタグ

.sticky_table thead,
.sticky_table tbody {
  display: block;
  width: -webkit-max-content;
  width: -moz-max-content;
  width: max-content;
}

theadとtbodyタグは幅を子要素のとりうる最大の横幅となるようwidth: max-contentを指定します。

なお、max-contentはブラウザによって対応状況が異なります。
Intrinsic & Extrinsic Sizing | Can I use...

th, tdタグ

.sticky_table th,
.sticky_table td {
  display: inline-block;
  width: 8.0rem;
  background: #fff;
  font-size: 1.0rem;
}

thとtdタグはdisplay: inline-blockとし、横並びに整列させ、widthで横幅を固定します。

backgroundはスクロールした際、固定要素と文字が重なるのを回避するため指定します。

列ヘッダの固定

.sticky_table tbody th {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 1;
}

列はtbodyの子要素thに対しposition: stickyを指定します。スクロールの際に左側に吸着するようleft: 0を指定します。

行ヘッダの固定

.sticky_table thead {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 2;
}

行はtheadに対しposition: stickyを指定します。スクロールの際に上側に吸着するようtop: 0を指定します。

行・列ヘッダの交差部分の固定

.sticky_table thead th.blank {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  left: 0;
  z-index: 3;
}

行・列ヘッダの交差部分はtheadのblankクラスを指定したthに対しposition: stickyを指定します。スクロールの際に左上に吸着するようtop: 0; left: 0を指定します。


ヘッダ固定テーブルの実装は以上です。

あとはCSSでデザインを行えば完成ですが、ここではヘッダ固定テーブルの実装について記すことが主旨のため、デザイン関連のコードは割愛させていただきます。Codepenをご参照ください。

Conclusion

CSSのみでヘッダ固定テーブルが実装できましたがこれで完成ではありません。

当初目的としていたものは、position: stickyの指定のみでtheadとtbody>thを固定する事でした。しかしながら各ブラウザの対応状況が異なるため、display属性をブロック要素にして対処しています。

ブロック要素を横並びにするためwidth: max-contentが必要になります。ブラウザの対応状況が進み、table部品にもposition: stickyが適用できるようになれば不要となり、より容易にヘッダ固定テーブルを実装することができるようになるでしょう。

Reference

CSS position: sticky | Can I use...
Intrinsic & Extrinsic Sizing | Can I use...

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away