DEV Community

Cover image for A table with a fixed (sticky) header
debadeepsen
debadeepsen

Posted on

A table with a fixed (sticky) header

Often, we come across situations where we have a table with lots of data in it. So when we scroll, the table header are hidden off screen, and soon we don't know what columns we're looking at. This problem can easily be addressed by wrapping the table in a div, and a bit of friendly CSS.

position: sticky

Sticky positioning is kind of a hybrid, between relative and fixed. To quote https://developer.mozilla.org/en-US/docs/Web/CSS/position, "The element is positioned according to the normal flow of the document, and then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor), including table-related elements, based on the values of top, right, bottom, and left." Basically, the element occurs in the normal document flow, until you scroll past a certain offset, at which point it sticks to the top of the specified container.

We're going to wrap our table in a div (which we'll make scrollable by setting its height and overflow-y properties), and make the ths position in a sticky way. We'll also collapse the internal borders of the table using the border-collapse property. Is it really that simple? It actually is.

Here's the code, in its full unadulterated glory (don't worry, I didn't include any spoiler from season 2 of The Umbrella Academy, but seriously, go watch it):

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Sticky Header</title>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="src/styles.css" />
  </head>

  <body>
    <div class="wrapper">
      <table>
        <thead>
          <tr>
            <th>Number</th>
            <th>Name</th>
            <th>Superpower</th>
            <th>Email</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>1</td>
            <td>Luther</td>
            <td>Super-strength</td>
            <td>luther@umbrella.edu</td>
          </tr>
          <tr>
            <td>2</td>
            <td>Diego</td>
            <td>Telekinesis</td>
            <td>diego@umbrella.edu</td>
          </tr>
          <tr>
            <td>3</td>
            <td>Allison</td>
            <td>Rumor</td>
            <td>allison@umbrella.edu</td>
          </tr>
          <tr>
            <td>4</td>
            <td>Klaus</td>
            <td>Seance</td>
            <td>klaus@umbrella.edu</td>
          </tr>
          <tr>
            <td>5</td>
            <td>Five</td>
            <td>Time-travel</td>
            <td>five@umbrella.edu</td>
          </tr>
          <tr>
            <td>6</td>
            <td>Ben</td>
            <td>Inter-dimensional monster</td>
            <td>ben@umbrella.edu</td>
          </tr>
          <tr>
            <td>7</td>
            <td>Vanya</td>
            <td>Apocalyptic destruction</td>
            <td>vanya@umbrella.edu</td>
          </tr>
          <tr>
            <td>-</td>
            <td>Reginald</td>
            <td>[Spoiler] powers</td>
            <td>reginald@umbrella.edu</td>
          </tr>
          <tr>
            <td>-</td>
            <td>Pogo</td>
            <td>Human communication</td>
            <td>pogo@umbrella.edu</td>
          </tr>
          <tr>
            <td>-</td>
            <td>Cha-Cha</td>
            <td>Ruthlessness</td>
            <td>chacha@temps.comm</td>
          </tr>
          <tr>
            <td>-</td>
            <td>Hazel</td>
            <td>Compassion</td>
            <td>hazel@temps.comm</td>
          </tr>
        </tbody>
      </table>
    </div>
  </body>
</html>

CSS

body {
  font-family: "Segoe UI", sans-serif;
}

table {
  width: 100%;
  border-collapse: collapse;
}

th,
td {
  padding: 8px;
}

th {
  text-align: left;
  background: #eee;
  position: sticky;
  top: 0px;
}

.wrapper {
  border: 1px solid #ddd;
  width: 100%;
  height: 300px;
  overflow-y: auto;
}

You can see the above example running on CodeSandbox here - https://codesandbox.io/s/determined-buck-396hm

So long for now, and happy positioning!

Top comments (1)

Collapse
 
jpwelch profile image
J P Welch

I read this post, copied the CSS code into my site and the table headers appear fixed when previewing the TablePress tables; however, on the site, they don't. I don't know code and wonder if the problem is the WordPress Lawyer Zone Pro theme I'm using or I've missed something in the CSS code. Thanks.
pfr.guide/visit-a-country/find-a-s...
pfr.guide/take-a-cruise/find-a-saf...