[小ネタ]Chakra UI のテーブルでヘッダを固定表示してみた

2022.08.24

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

最近、Next.js でUIコンポーネントの Chakra UI を利用しています。

このコンポーネントでテーブルを表示する際に「ヘッダを固定表示したい!」と思い、実装対応することができたので、対応方法を残しておきたいと思います。

先に結論

TableContainerThead を以下のように設定します。

        <TableContainer overflowX="unset" overflowY="unset">
          <Table variant="simple">
            <Thead position="sticky" top={0} zIndex="docked">

解説

どうやって対応すると良いか悩んでいたのですが、以下のIssueのコメントを見つけて対応をしました。

やりたいこととしては「CSSのposition: stickyを適用する」になりますが、ポイントとしてTableContaineroverflowを持っているのでunsetを指定して解除しています。

具体的なサンプルとしては以下のようなコードになります。

sticky-table.tsx

import { Box, ChakraProvider, Table, TableContainer, Tbody, Td, Th, Thead, Tr } from '@chakra-ui/react'

function StickyTable() {
  const cols = [
    { id: 0, name: 'ID' },
    { id: 1, name: '都道府県名' },
  ]
  const rows = [
    { id: 0, values: ['01', '北海道'] },
    { id: 1, values: ['02', '青森県'] },
    { id: 2, values: ['03', '岩手県'] },
    { id: 3, values: ['04', '宮城県'] },
    { id: 4, values: ['05', '秋田県'] },
    { id: 5, values: ['06', '山形県'] },
    { id: 6, values: ['07', '福島県'] },
    { id: 7, values: ['08', '茨城県'] },
    { id: 8, values: ['09', '栃木県'] },
    { id: 9, values: ['10', '群馬県'] },
    { id: 10, values: ['11', '埼玉県'] },
    { id: 11, values: ['12', '千葉県'] },
    { id: 12, values: ['13', '東京都'] },
    { id: 13, values: ['14', '神奈川県'] },
    { id: 14, values: ['15', '新潟県'] },
    { id: 15, values: ['16', '富山県'] },
    { id: 16, values: ['17', '石川県'] },
    { id: 17, values: ['18', '福井県'] },
    { id: 18, values: ['19', '山梨県'] },
    { id: 19, values: ['20', '長野県'] },
    { id: 20, values: ['21', '岐阜県'] },
    { id: 21, values: ['22', '静岡県'] },
    { id: 22, values: ['23', '愛知県'] },
    { id: 23, values: ['24', '三重県'] },
    { id: 24, values: ['25', '滋賀県'] },
    { id: 25, values: ['26', '京都府'] },
    { id: 26, values: ['27', '大阪府'] },
    { id: 27, values: ['28', '兵庫県'] },
    { id: 28, values: ['29', '奈良県'] },
    { id: 29, values: ['30', '和歌山県'] },
    { id: 30, values: ['31', '鳥取県'] },
    { id: 31, values: ['32', '島根県'] },
    { id: 32, values: ['33', '岡山県'] },
    { id: 33, values: ['34', '広島県'] },
    { id: 34, values: ['35', '山口県'] },
    { id: 35, values: ['36', '徳島県'] },
    { id: 36, values: ['37', '香川県'] },
    { id: 37, values: ['38', '愛媛県'] },
    { id: 38, values: ['39', '高知県'] },
    { id: 39, values: ['40', '福岡県'] },
    { id: 40, values: ['41', '佐賀県'] },
    { id: 41, values: ['42', '長崎県'] },
    { id: 42, values: ['43', '熊本県'] },
    { id: 43, values: ['44', '大分県'] },
    { id: 44, values: ['45', '宮崎県'] },
    { id: 45, values: ['46', '鹿児島県'] },
    { id: 46, values: ['47', '沖縄県'] },
  ]

  return (
    <ChakraProvider>
      <Box bg="blue.100" w="100%" p={5} borderWidth="1px">
        <TableContainer overflowX="unset" overflowY="unset">
          <Table variant="simple">
            <Thead position="sticky" top={-1} zIndex="docked">
              <Tr bg="gray.100">
                {cols.map((col) => (
                  <Th key={col.name} borderWidth="1px" borderColor="gray.200">
                    {col.name}
                  </Th>
                ))}
              </Tr>
            </Thead>
            <Tbody>
              {rows.map((row) => (
                <Tr key={row.id}>
                  {cols.map((col) => (
                    <Td key={`${col.id}-${row.id}`} borderWidth="1px" borderColor="gray.200" bg="white">
                      {row.values[col.id]}
                    </Td>
                  ))}
                </Tr>
              ))}
            </Tbody>
          </Table>
        </TableContainer>
      </Box>
    </ChakraProvider>
  )
}

export default StickyTable

こうすると、初期表示は以下のようになります。

また、このテーブルを下にスクロールしていくと、テーブルヘッダが上部に残り、常にヘッダの内容を把握しながらテーブルデータを見ることができます。

なお、このサンプルではTheadtopには-1を指定しています。この値が0だと、固定ヘッダと画面上部の間に微妙な隙間が開いてしまうので、-1を指定することで隙間を埋めています。

まとめ

以上、Chakra UI のテーブルでヘッダを固定表示してみました。

「テーブルのヘッダを固定表示する」というユースケースは割とあるかと思うので、忘れないようにしたいと思います。

どなたかのお役に立てば幸いです。それでは!