bytes.zone

sticky table headers with bottom borders

Brian Hicks, November 13, 2023

Say you have a table like this:

<table>
  <thead>
    <tr>
      <th>Column 1</th>
      <th>Column 2</th>
      <th>Column 3</th>
    </tr>
  </thead>
  <tbody>
    <!-- ... -->
  </tbody>
</table>

You might try to separate the header from the body like this:

table.fancy > thead > tr {
  border-bottom: 1px solid #ccc;
}

That works, but what if you want the <thead> element to have position: sticky too? If you used a border, the border will keep scrolling while the header sticks. Oh no!

I got around this by using box-shadow instead. It works, despite feeling a little hacky:

table.fancy > thead > tr {
  box-shadow: inset 0px -1px #ccc;
}

Except that Safari won't display the shadow below the header. More hacks required! Apply the shadow to all the cells inside it:

table.fancy > thead td {
  box-shadow: inset 0 -1px #ccc;
}

This feels even hackier than the original fix, but it works fine in all the browsers that I tested!

If you'd like me to email you when I have a new post, sign up below and I'll do exactly that!

If you just have questions about this, or anything I write, please feel free to email me!