🖥

Tailwind CSS だけでテーブルの縦横2列を固定してスクロールできるようにする

2024/03/24に公開

動作例

https://play.tailwindcss.com/XAqGKfe1E8

HTML例

  • テーブル内の全てのセルには最大幅・最小幅を指定して、セルの幅を固定している。
  • テーブル内の全てのセルにはフォントサイズ・余白を設定してセルの高さを固定している。なぜならテーブルセルの仕様的にセル自体に高さを直接指定できないため。
  • 固定するセルには全て sticky を指定する
  • 2行目の固定行ではセルの固定縦幅分のtopを指定して表示位置を下にずらしている
  • 2列目の固定列ではセルの固定縦幅分のleftを指定して表示位置を右にずらしている
  • 固定するセルには背景色を指定して、他のセルが重なった時に文字が透けて重ならないようにしている
  • それぞれのセルに必要な z-index ( z-数字 ) を指定して表示の優先度をつけ、セルが重なった時の制御をしている
  <!-- テーブル全体の幅・高さ・スクロール指定 -->
  <div class="h-[240px] w-[480px] overflow-scroll">
    <table class="border-collapse text-center text-[1rem] leading-4">
      <thead>
        <!-- テーブルヘッダの1行目 -->
        <tr>
          <!-- テーブルヘッダ1行目 > 左から1個目のセル -->
          <!-- top / left は 0 -->
          <!-- z-index 指定は最優先 -->
          <th
            class="sticky left-0 top-0 z-30 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]"
          >
            cell_01-01
          </th>

          <!-- テーブルヘッダ1行目 > 左から2個目のセル -->
          <!-- 固定幅分の left を指定して右に位置をずらしている -->
          <!-- z-index 指定は最優先 -->
          <th
            class="sticky left-[6rem] top-0 z-30 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]"
          >
            cell_01-02
          </th>

          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-03
          </th>

          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-04
          </th>
          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-05
          </th>
          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-06
          </th>
          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-07
          </th>
          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-08
          </th>
          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-09
          </th>
          <th class="sticky top-0 z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_01-10
          </th>
        </tr>

        <tr>
          <!-- テーブルヘッダ2行目 > 左から1個目のセル -->
          <!-- 固定縦幅分の top を指定して下に位置をずらしている -->
          <!-- z-index 指定は最優先 -->
          <th
            class="sticky left-0 top-[2rem] z-30 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]"
          >
            cell_02-01
          </th>

          <!-- テーブルヘッダ2行目 > 左から2個目のセル -->
          <!-- 固定縦幅分の top を指定して下に位置をずらしている -->
          <!-- z-index 指定は最優先 -->
          <th
            class="sticky left-[6rem] top-[2rem] z-30 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]"
          >
            cell_02-02
          </th>

          <!-- テーブルヘッダ2行目 > 左から3列目以降の全てのセル -->
          <!-- 横の位置は固定するが、縦の位置は固定しない -->
          <!-- z-index 指定の優先度は2番目 -->
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-03
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-04
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-05
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-06
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-07
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-08
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-09
          </th>
          <th class="sticky top-[2rem] z-20 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-pink-200 p-[0.5rem]">
            cell_02-10
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_03-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_03-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_03-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_04-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_04-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_04-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_05-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_05-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_05-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_06-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_06-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_06-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_07-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_07-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_07-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_08-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_08-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_08-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_09-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_09-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_09-10</td>
        </tr>
        <tr>
          <td class="sticky left-0 z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]">
            cell_10-01
          </td>
          <td
            class="sticky left-[6rem] z-10 max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] bg-blue-200 p-[0.5rem]"
          >
            cell_10-02
          </td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-03</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-04</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-05</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-06</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-07</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-08</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-09</td>
          <td class="max-h-[2rem] min-h-[2rem] min-w-[6rem] max-w-[6rem] p-[0.5rem]">cell_10-10</td>
        </tr>
      </tbody>
    </table>
  </div>

参考

素のCSSで組まれた「CSSだけでテーブルの縦横2列を固定してスクロールできるようにする」のサンプルを参考に、Tailwind CSSに置き換えて試してみた

https://zenn.dev/mryhryki/articles/2019-12-31-hatena-fixed-header-table-css

https://stackblitz.com/edit/scrolltable-with-fixed-2rows-2columns-header?file=index.html

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ

プロフィール・経歴

https://github.com/YumaInaura/YumaInaura

公開日時

2024-03-15

Discussion