📝

とある小難しいtableのスタイリング(&マークアップ)の考え方の記録

2023/02/06に公開

はじめに

こんな要件の表をレイアウトすることになった

うわぁ嫌だ・・・
何が、って太線と通常線があり、シンプルではないルールで使い分けられている。
表であるため、<table>タグを利用するのがシンプルでありそうだが、ちょっと難しそう。
そして、見た目はスッキリしていていいのですが、枠線が色々なパターンで出たり出なかったりしています。

で、そもそものデザインを見直したほうがよいかも?とは思いましたがもう確定させているので、これに向き合う必要がある。
UIフレームワーク・・・はこれだけのために入れたくない。
table使う(覚悟)

・・・みたいなことが未来の自分にもまた起きそうだし記事化しておくことにしました。

やってみたこと

要件のリストアップ

とりあえず、特徴を列挙してみる

  • 行のヘッダがある(項目1, 項目2・・・合計)
    • 空白
    • 項目N
    • 合計
  • 列のヘッダがある(1月, 2月〜12月)
    • M月
  • 項目 x 月別データがある
    • 整数1〜2桁
  • 月別の合計データがある
    • 整数1〜2桁
  • 枠線が2種類使われている
    • ヘッダとデータの区切りが太線
    • ヘッダの区切りが太線
      • 例えば、項目1・項目2の間は通常線

要件の整理

  • 1つのテーブルだけ利用
  • セルはヘッダとデータの二種類で利用
  • ヘッダは行ヘッダ用と列ヘッダ用の2つを利用
  • ヘッダ
    • 行ヘッダの上に枠線をつける
      • ただし、
        • 最初は枠線をつけない
        • 項目ヘッダと合計ヘッダの最初だけ太枠線をつける
    • 列ヘッダの右に枠線をつける
      • ただし、
        • 最初だけ太枠線をつける
        • 最後は枠線をつけない
  • データ
    • すべて枠線をつける
      • ただし、
        • 最後のセルは右枠線をつけない
        • 最後のセルで、かつ最後の行に属する場合には下枠線をつけない

マークアップしてみる

以下をポリシーにとりあえずマークアップ

  • 次の情報構造とする
    • 行ヘッダ
      • ブランク(左上隅となる部分)
      • データ部のヘッダ
      • 合計部のヘッダ
    • 列ヘッダ
      • N月 x 12
    • データ
  • 構造化のため、行ヘッダにクラスをつけて区別できるようにミニマムなクラスつけ
    • 行ヘッダ
      • ブランク(左上隅となる部分) with no-named
      • データ部のヘッダ as unit
      • 合計部のヘッダ as aggregate

※強めのリセットCSS(destyle)を入れています

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/destyle.css@1.0.15/destyle.css"
  />
  <title>Document</title>
</head>
<body>
  <table>
    <tbody>
      <tr>
        <th></th>
        <th>1月</th>
        <th>2月</th>
        <th>3月</th>
        <th>4月</th>
        <th>5月</th>
        <th>6月</th>
        <th>7月</th>
        <th>8月</th>
        <th>9月</th>
        <th>10月</th>
        <th>11月</th>
        <th>12月</th>
      </tr>
      <tr class="unit first">
        <th>行1</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
        <td>8</td>
        <td>9</td>
        <td>10</td>
        <td>11</td>
        <td>12</td>
      </tr>
      <tr class="unit">
        <th>行2</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
        <td>8</td>
        <td>9</td>
        <td>10</td>
        <td>11</td>
        <td>12</td>
      </tr>
      <tr class="aggregate">
        <th >合計値</th>
        <td>2</td>
        <td>4</td>
        <td>6</td>
        <td>8</td>
        <td>10</td>
        <td>12</td>
        <td>14</td>
        <td>16</td>
        <td>18</td>
        <td>20</td>
        <td>22</td>
        <td>24</td>
      </tr>
    </tbody>
  </table>  
</body>
</html>

スタイリングしてみる

<style>

/* 行ヘッダの上に枠線をつける */
tr {
  border-top: 1px solid;
}

/* 最初は枠線をつけない */
tr:first-child {
  border-top: 0;
}

/* 項目ヘッダと合計ヘッダの最初だけ太枠線をつける */
tr.unit.first,
tr.aggregate {
  border-top: 3px solid;
}

/* 列ヘッダの右に枠線をつける */
th {
  border-right: 1px solid;
}

/* 最初だけ太枠線をつける */
tr th:first-child {
  border-right: 3px solid;
}

/* 最後は枠線をつけない */
tr th:last-child {
  border-right: 0;
}

/* データセルはすべて枠線をつける */
td {
  border: 1px solid;
}

/* 最後のセルは右枠線をつけない */
td:last-child{
  border-right: 0;
}

/* 最後のセルで、かつ最後の行に属する場合には下枠線をつけない */
tr:last-child td{
  border-bottom: 0;
}

</style>

結果

最後に

cssなんて1バイトも書きたくない、とは思いつつうまくディレクションできなかった。
同じような状況に向き合う人が少しはいると信じてこの記事を公開します。
少なくとも半年以上あとの自分に向けて・・

Discussion