モダンCSSで様々なバリエーションのテーブルを実装する

モダンCSSで実装する、テーブル()のさまざまなスタイルのまとめ
...

使用するテーブル(HTML)は以下の通り。

<table>
  <caption>ヒーロー</caption>
  <colgroup><col><col><col><col></colgroup>
  <thead>
    <tr><th>ファーストネーム</th><th>ラストネーム</th><th>ヒーロー</th><th>場所</th></tr>
  </thead>
  <tbody>
    <tr><td>ブルース</td><td>ウェイン</td><td>バットマン</td><td>ゴッサム・シティ</td></tr>
    <tr><td>クラーク</td><td>ケント</td><td>スーパーマン</td><td>メトロポリス</td></tr>
    <tr><td>トニー</td><td>スターク</td><td>アイアンマン</td><td>マリブ</td></tr>
    <tr><td>ピーター</td><td>パーカー</td><td>スパイダーマン</td><td>ニューヨーク</td></tr>
    <tr><td>マット</td><td>マードック</td><td>デアデビル</td><td>ニューヨーク</td></tr>
  </tbody>
</table>

テーブルを構成するHTMLの要素

テーブル内のデータを読みやすくするために、:is(td, th){}セレクタにpadding: .5ch 1ch;を追加し、<caption>にmargin-block: 1rlh;を追加する。

table {
  border-collapse: collapse;
  font-family: system-ui;
  caption-side: bottom; // <caption>をテーブルの下に配置する場合
  & caption { margin-block: 1rlh; }
  &:is(td, th) {
    border-style: solid;
    padding: .5ch 1ch;
  }
}

テーブルをゼブラストライブにするCSS

テーブルの列をゼブラストライプにするには、<col>にスタイルを設定するだけである。

col:nth-of-type(even) { background: #F2F2F2; }

行の場合は、<tr>に指定する。

tr:nth-of-type(odd) { background: #F2F2F2; }

テーブルを角丸にするCSS

<table>にborder-radiusを単に追加するだけでは実現できないため、最初と最後の行の最初と最後のセルをターゲットにする。
ただしボーダーがcollapseの場合、border-radiusが追加できないため、ボーダーを分割して使用し、collapseのボーダーを模倣する必要がある。

.rounded th:first-of-type {
   border-start-start-radius: 0.5em;
}
.rounded th:last-of-type {
   border-start-end-radius: 0.5em;
}
.rounded tr:last-of-type td:first-of-type {
   border-end-start-radius: 0.5em;
}
.rounded tr:last-of-type td:last-of-type {
   border-end-end-radius: 0.5em;
}
table.rounded {
  border-spacing: 0;
}
.rounded :is(td, th) {
   border-block-width: 1px 1px;
   border-inline-width: 1px 0;
}
.rounded :is(td, th):last-of-type {
   border-block-end-width: 1px;
   border-inline-end-width: 1px;
}
.rounded tr:not(:last-child)>td, .rounded tr:last-child>th{
  border-block-end-width: 0;
}

テーブルの列を分割するCSS

独立した列を維持し、border-spacingプロパティでカラム間にスペースを追加する。
これは単なる<table>だが、比較表として使用するとさらに読みやすくなる。

table {
  border-spacing: 2ch 0;
  & :is(td, th) {
    border-inline-width: 1px;
  }
}

テーブルの行を分割するCSS

行を独立させるためには、border-spacingプロパティの2番目(y軸)をアップデートするだけである。

table {
  border-spacing: 0 2ch;
  & :is(td, th) {
    border-block-width: 1px;
  }
}

ホバー・フォーカスでハイライトするCSS

テーブルが大きいと、どこを見ているか把握することが難しいかもしれない。そこで役立つのが、:hoverである。また、キーボードでナビゲート可能なテーブルを使用している場合は、:focus-visbleが必要になる。

行と列のホバー時にハイライトさせるのは簡単である。

td:hover {
  background: #666666;
} 
tr:hover {
  background: #E6E6E6;
}

<col>のホバーは少し複雑で、:hasを使用してセルのホバーをキャプチャし、<col>要素にスタイルを設定する。

table {
  &:has(:is(td,th):nth-child(1):hover col:nth-child(1) {
  background: #E6E6E6;
}

テーブルの<td>または<th>がnth-child(1)であり、現在ホバーされている場合、同じnth-childを持つ<col>を選択し、backgroundを設定する。
そして、このCSSを各列に対して繰り返す必要がある(nth-child(2), nth-child(3)など)。

ホバーでアウトラインを表示するCSS

ホバー時にアウトラインを表示するのも簡単で、セルと行も同じである。ただしオフセットから幅を引く必要がある。

:is(td, th, tr):hover {
  outline: 2px solid #666;
  outline-offset: -2px;
}

列のアウトラインを作成するのは非常に難しいが、見栄えは良くなる。

セルのborder-widthが1pxの場合、<col>のホバー時にborder-widthを2pxに設定できるが、そうするとテーブル全体がずれてしまう。そのため、<col>に背景グラデーションでボーダーをシミュレートする方法がある。テーブルのセルが透明であれば、これはうまく機能する。
border-radiusで動作させ、セルの背景を維持するため、セルごとに疑似要素を使用する。
そして、col-hoverで行ったことと同様に、ホバー時に同じcol-indexを持つすべてのセルをターゲットにする。

:is(td,th) {
  position: relative;
  &::after {
    border-inline: 2px solid transparent;
    border-radius: inherit;
    content: '';
    inset: -2px 0 0 0;
    position: absolute;
  }
}
tr:first-of-type th::after {
  border-block-start: 2px solid transparent;
}
tr:last-of-type td::after {
  border-block-end: 2px solid transparent;
}
:has(:is(td,th):nth-child(1):hover :is(td,th):nth-child(1) {
  border-color: #666;
}

データを左右・中央に揃えるCSS

古い仕様では、<col>要素にalignプロパティを追加できたが、これはもう機能しない。
たとえば、2列目のテキストを中央揃えにして、4列目のテキストを右揃えにしてみる。

[data-c2~="center"] tr > *:nth-of-type(2) {
  text-align: center;
}
[data-c4~="end"] tr > *:nth-of-type(4) {
  text-align: end;
}

各セルにクラスを追加する代わりに、テーブル全体に列ごとにデータ属性を追加する。
あとは、すべての列に対してこれを繰り返す。

<table data-c2="center" data-c4="end">
inserted by FC2 system