Search code examples
javascripthtmlcssreactjstailwind-css

Tailwindcss table with fixed header and scrollable body


I am trying to build a table that has a fixed header with a scrollable body using Tailwind. Note that only the body of the table should be scrollable and not the surrounding div. This, to prevent the scrollbar from laying over the header.

This is my table:

 <div
  class="h-full border-separate overflow-clip rounded-xl border border-solid"
>
  <table class="w-full table-fixed flex-col">
    <thead class="sticky top-0">
      <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Country</th>
      </tr>
    </thead>
    <tbody class="inline-block h-96 w-96 overflow-y-scroll">
      <For each={props.users.items}>
        {(user) => (
          <tr
            class="cursor-pointer space-x-2"
          >
            <td>
              {user.firstName} {user.lastName}
            </td>
            <td>{user.email}</td>
            <td>{user.country}</td>
          </tr>
        )}
      </For>
    </tbody>
  </table>
</div>

In the parent component i have a div surrounding the table with a flex-1.

Currently with the example above the table is behaving as intended but the height and width are hardcoded and do not match the height and width of the table, they should fill the space available instead. If i remove the inline-block with the hardcoded width and height, the table looks exactly how it should but then its not scrollable.

Any suggestions or ideas as to what is causing this? Thanks


Solution

  • One way to make only the tbody scrollable while filling the available space is to use a combination of flex and overflow-y-auto.

    <div class="h-full border-separate overflow-clip rounded-xl border border-solid flex flex-col">
      <table class="w-full table-fixed">
        <thead class="sticky top-0">
          <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Country</th>
          </tr>
        </thead>
      </table>
      <div class="flex-1 overflow-y-auto">
        <table class="w-full table-fixed">
          <tbody>
            <For each={props.users.items}>
              {(user) => (
                <tr class="cursor-pointer space-x-2">
                  <td>
                    {user.firstName} {user.lastName}
                  </td>
                  <td>{user.email}</td>
                  <td>{user.country}</td>
                </tr>
              )}
            </For>
          </tbody>
        </table>
      </div>
    </div>
    

    Tailwind PLayground