Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sticky table header with two header rows

Considering the following table structure:

<table border="1px">
  <thead>
    <tr>
        <td rowspan="2">Item No</td>
        <th colspan="2">Store ABC</th>
        <th colspan="2">Store DEF</th>
    </tr>
    <tr>
        <th>Baskets</th>
        <th>Customers</th>
        <th>Baskets</th>
        <th>Customers</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>

I would like to make the table-header sticky so that when scrolling down the table, it remains visible.

Easy thing when there is only one header row. However, things get tricky when having two. I've come up with the following css:

thead th, thead td {
  position: sticky;
  top: 0;
  background: #eee;
}

It "almost" works, except when scrolling the table, the two header rows kind of "slip" to the same position, the second row coming on top of the first one.

How to make the two header rows sticky in a way that their appearance is not changed when scrolling down the table (i.e. the whole header remains a "block" and its two distinct rows stay in place)?

Mandatory jsFiddle: http://jsfiddle.net/juyvcLd6/3/

--- UPDATE

Identifying the two header rows with class="first" and class="second" respectively, plus adding the following css:

thead tr.first th, thead tr.first td {
  position: sticky;
  top: 0;
  background: #eee;
}

thead tr.second th, thead tr.second td {
  position: sticky;
  top: 17px;
  background: #eee;
}

has the effect of keeping the header rows together in place while scrolling the table. However, the top: 17px element is very much dependent on the actual rendered size of the row. If the user has its browser rendering text sizes differently, for instance, then everything will go off.

Plus, this method has the drawback of getting rid of header borders in quite a weird way.

How to make sure that, when scrolling the table:

  1. the top: xxx rule for the second row actually reflects the real height of the first row?
  2. the borders stay consistent with what they look like when the table is not scrolled?

See updated jsFiddle: http://jsfiddle.net/juyvcLd6/4/

like image 898
Jivan Avatar asked Apr 14 '19 09:04

Jivan


1 Answers

Since all your header rows are in thead, just apply the position: sticky; to thead instead of thead th, thead td. In this way you don't need to worry about the height of each header row or how many header row you have.

thead {
  position: sticky;
  top: 0;
  background: #eee;
}

I made the change to your first example and it works. https://jsfiddle.net/qcuxkng5/

table {
  height: 100%;
  border-collapse: collapse;
  width: 100%;
  margin: 10px;
  font-size: 0.8em;
}

thead {
  position: sticky;
  top: 0;
  background: #eee;
}
<table border="1px">
  <thead>
    <tr>
        <td rowspan="2">Item No</td>
        <th colspan="2">Store ABC</th>
        <th colspan="2">Store DEF</th>
    </tr>
    <tr>
        <th>Baskets</th>
        <th>Customers</th>
        <th>Baskets</th>
        <th>Customers</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
    <tr>
      <th>123</th>
      <td>345</td>
      <td>345</td>
      <td>345</td>
      <td>345</td>
    </tr>
  </tbody>
</table>
like image 182
Haoshu Avatar answered Oct 19 '22 00:10

Haoshu