[CSS]テーブルのレスポンシブ対応例。SPでは別の表に分割、PCではひとつの表にまとめる力技。


tableタグのレスポンシブ対応は毎度工夫が必要だと感じています。
何度かtableのレスポンシブ対応例は投稿しているので、もしよろしければ他の記事もご覧ください。

今回は、料金表のような比較表をスマホサイズでも横スクロールなしで表示する事例を紹介いたします。

## 仕様と表示例

まずは完成イメージです。

以下がPCモニターでの表示イメージです。
プラン別の料金比較表を想定しています。

![スクリーンショット 2023-07-01 0.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62022/67cb86f3-e756-4f27-d00e-9f5b5c19a56d.png "スクリーンショット 2023-07-01 0.16.42.png")

次にSPモニターでの表示イメージです。

![スクリーンショット 2023-07-01 0.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62022/36b0c5bb-5ae9-679f-e3b0-a358837a0560.png "スクリーンショット 2023-07-01 0.19.40.png")

* PCは横並び/SPは縦並び
* SPは非対応の項目（空白のセル）は表示しない

という仕様になります。
項目数が多かったりテキスト量が多いケースでは、こちらの方がすっきりして見やすいかもしれません。

## 実装

### HTML

html側にはPC用の横並び表しか記述しません。
SP用のコードはJavaScriptで動的に挿入します。
そのため、SP用tableを挿入する箇所をID指定する必要があります。


```html
<!-- bootstrapのclass名を記入していますが、class名は任意です -->
<table class="table table-striped">
    <thead class="table-dark">
        <tr>
            <th></th>
            <th>プランA</th>
            <th>プランB</th>
            <th>プランC</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th>基本料金</th>
            <td>10,000円</td>
            <td>50,000円</td>
            <td>100,000円</td>
        </tr>

        <tr>
            <th>項目①</th>
            <td>メニューA</td>
            <td>メニューB</td>
            <td>メニューC</td>
        </tr>

        <tr>
            <th>項目②</th>
            <td></td>
            <td>メニューB</td>
            <td>メニューC</td>
        </tr>

        <tr>
            <th>項目③</th>
            <td></td>
            <td></td>
            <td>メニューC</td>
        </tr>
    </tbody>
</table>

<!-- SP用tableを挿入する箇所 -->
<div id="resTable"></div>

```

PC用tableの```<thead>```からプラン名を、```<tbody>```内```<td>```からテキストをそれぞれ取得するので、各タグは省略せず記述してください。

### JavaScript


```.table```というclass名はHTMLの```<table>```に指定したclass名に書き換えてください。


```javascript
const resTable = document.getElementById('resTable'); // tableを挿入するdivを指定
const arrayMenu = [];

// 項目名を取得し配列に追加
document.querySelectorAll('.table > tbody > tr').forEach(function(menuName, index) {
  arrayMenu.push(menuName.children[0].innerHTML);
});

// 各プランの処理
document.querySelectorAll('.table > thead th').forEach(function(planName, index) {

  if (index > 0) { // 空白セルを無視

    const planTableSP = document.createElement('table');
    planTableSP.classList.add('table', 'table-striped'); // tableに追加するclass名。不要なら無しでOK

    const planClass = planName.getAttribute('class');

    // プラン名を挿入
    const tHead = document.createElement('thead');
    const tRow = document.createElement('tr');
    const thCell = document.createElement('th');

    tHead.classList.add('table-dark'); // 「プラン名」の<thead>に追加するclass名。不要なら無しでOK
    thCell.setAttribute('colspan', '2');
    thCell.classList.add(planClass, 'text-center'); // 「プラン名」の<th>に追加するclass名。不要なら無しでOK
    thCell.innerHTML = planName.innerHTML;
    tRow.appendChild(thCell);
    tHead.appendChild(tRow);
    planTableSP.appendChild(tHead);

    // tbody生成
    const tBody = document.createElement('tbody');

    // 各項目の処理
    document.querySelectorAll('.table > tbody > tr').forEach(function(row, rowIndex) {

      const menuRow = document.createElement('tr'); // tr生成
      const menuCell = document.createElement('th'); // th生成
      menuCell.innerHTML = arrayMenu[rowIndex];

      // 空白の項目は無視
      if (row.children[index].textContent !== '') {

        const menuContent = document.createElement('td'); // td生成
        menuContent.innerHTML = row.children[index].innerHTML;

        // trにth/tdを追加
        menuRow.appendChild(menuCell);
        menuRow.appendChild(menuContent);

        // tableにtrを追加
        planTableSP.appendChild(menuRow);
      } // if

    }); // forEach

    // 指定divに生成したtableを挿入
    resTable.appendChild(planTableSP);

  } // if

});
```

これでページを表示すると、元のPC用tableの下に動的に追加されたSP用のtableも表示されているのを確認できると思います。

あとは端末別に適切に表示すればいいので、JavaScriptなりCSSなりで対応しましょう。

力技ではありますが、ユーザーに適切に情報を届けることが優先されるべきなので、必ずしもCSSだけでレスポンシブ対応する必要は無いと思っています。

何かの参考になりましたら幸いです。