W3docs

How to Create a Table with a Fixed Header and Scrollable Body

In this tutorial, find some methods of creating an HTML table with a fixed header and scrollable body. Here, we suggest using some methods. See examples.

Solutions with CSS properties

In this tutorial, find some methods of creating an HTML table, which has a fixed header and scrollable body. Of course, you need to use CSS.

It is possible to achieve such a result by setting the position property to “sticky” and specifying 0 as a value of the top property for the <th> element.

As usual, you can open the <u>Try it Yourself</u> demo link and play with the properties to understand them better.

You can also read the comments in front of each line to understand the properties better.

Example of creating a table with a scrollable body by using the position property:

Example of creating a table with a scrollable body by using the position property:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .tableFixHead {
        overflow-y: auto; /* make the table scrollable if height is more than 200 px  */
        height: 200px; /* gives an initial height of 200px to the table */
      }
      .tableFixHead thead th {
        position: sticky; /* make the table heads sticky */
        top: 0px; /* table head will be placed from the top of the table and sticks to it */
      }
      table {
        border-collapse: collapse; /* make the table borders collapse to each other */
        width: 100%;
      }
      th,
      td {
        padding: 8px 16px;
        border: 1px solid #ccc;
      }
      th {
        background: #eee;
      }
    </style>
  </head>
  <body>
    <div class="tableFixHead">
      <table>
        <thead>
          <tr>
            <th>Col 1</th>
            <th>Col 2</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>1.1</td>
            <td>2.1</td>
          </tr>
          <tr>
            <td>1.2</td>
            <td>2.2</td>
          </tr>
          <tr>
            <td>1.3</td>
            <td>2.3</td>
          </tr>
          <tr>
            <td>1.4</td>
            <td>2.4</td>
          </tr>
          <tr>
            <td>1.5</td>
            <td>2.5</td>
          </tr>
          <tr>
            <td>1.6</td>
            <td>2.5</td>
          </tr>
          <tr>
            <td>1.7</td>
            <td>2.5</td>
          </tr>
          <tr>
            <td>1.8</td>
            <td>2.5</td>
          </tr>
        </tbody>
      </table>
    </div>
  </body>
</html>

Result

<div class="demo px-2.5 mt-1 mb-5 not-prose">``<div class="tableFixHead mb-30"> | Col 1 | Col 2 | |---|---| | 1.1 | 2.1 | | 1.2 | 2.2 | | 1.3 | 2.3 | | 1.4 | 2.4 | | 1.5 | 2.5 | | 1.6 | 2.5 | | 1.7 | 2.5 | | 1.8 | 2.5 |

</div> </div>Great! Huh? But let's face it! I don't like to see that scrollbar starting from the head section of the table!

So, let's continue to the next example and fix that issue together!

Thers's another method of creating a table with a fixed header and scrollable body. In the example below, we set the display to “block” for the <tbody> element so that it’s possible to apply the height and overflow properties.

Example of creating a table with a scrollable body by using the display property:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .fixed_header {
        width: 400px;
        table-layout: fixed;
        border-collapse: collapse;
      }
      .fixed_header tbody {
        display: block;
        width: 100%;
        overflow: auto;
        height: 100px;
      }
      .fixed_header thead tr {
        display: block;
      }
      .fixed_header thead {
        background: black;
        color: #fff;
      }
      .fixed_header th,
      .fixed_header td {
        padding: 5px;
        text-align: left;
        width: 200px;
      }
    </style>
  </head>
  <body>
    <table class="fixed_header">
      <thead>
        <tr>
          <th>Col 1</th>
          <th>Col 2</th>
          <th>Col 3</th>
          <th>Col 4</th>
          <th>Col 5</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
        <tr>
          <td>6</td>
          <td>7</td>
          <td>8</td>
          <td>9</td>
          <td>10</td>
        </tr>
        <tr>
          <td>11</td>
          <td>12</td>
          <td>13</td>
          <td>14</td>
          <td>15</td>
        </tr>
        <tr>
          <td>16</td>
          <td>17</td>
          <td>18</td>
          <td>19</td>
          <td>20</td>
        </tr>
        <tr>
          <td>21</td>
          <td>22</td>
          <td>23</td>
          <td>24</td>
          <td>25</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

As mentioned before, we used <span class="attribute">overflow: auto</span> on the <u>tbody</u> along with the <span class="attribute">display: block</span>.

Here's our result, and enjoy the difference!

Col 1Col 2Col 3Col 4Col 5
12345
678910
1112131415
1617181920
2122232425

As you have noticed, we didn’t use borders in the previous examples. However, if you need to add borders, you can simply use border property on all <span class="attribute">td</span> tags.

Example of creating a table with a scrollable body

.fixed_header td {
  border: 1px solid #797878;
}

And here's the result.

Col 1Col 2Col 3Col 4Col 5
12345
678910
1112131415
1617181920
2122232425

Hope you've enjoyed it!