Home > Mobile >  How to make a table head sticky but with overflow
How to make a table head sticky but with overflow

Time:10-13

I am trying to make the of a table sticky to top of page as you scroll, however the table width should be constrained by its parent and allow to scroll in the x direction.

However as soon as the overflow-x is added, the stickyness doesn't work, and if there's no overflow, then the head sticks, but the table content breaks the bounds of its parent container.

Example Pen https://codepen.io/JamesBlack91/pen/KKRJdQK

div {
  max-width: 300px;
  overflow-x: auto;
}

table thead {
  position: sticky;
  top: 0;
}
<div>
  <table>
    <thead>
      <tr>
        <th>Column 1</th>
        <th>Column 2</th>
        <th>Column 3</th>
        <th>Column 4</th>
        <th>Column 5</th>
        <th>Column 6</th>
        <th>Column 7</th>
        <th>Column 8</th>
        <th>Column 9</th>
        <th>Column 10</th>
        <th>Column 11</th>
        <th>Column 12</th>
        <th>Column 13</th>
        <th>Column 14</th>
        <th>Column 15</th>
        <th>Column 16</th>
        <th>Column 17</th>
        <th>Column 18</th>
        <th>Column 19</th>
        <th>Column 20</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
    </tbody>
  </table>
</div>

If you scroll, the head isn't sticky, but if you comment out the overflow on the div, the head is sticky but the columns overflow the 300px max.

I have read all about thead (previously) not supporting sticky, I've also tried on the < th > to no result. I've tried putting overflow on the table/thead/tbody instead of the ancestor div, but nothing seems to work.

I really want to avoid using javascript and I'm sure there's a simple css solution I just don't know.

CodePudding user response:

<style>
.lock-header { 
  height:100% !important;
} 
.lock-header thead th { 

}
.lock-header>table { 

}
.lock-header tfoot td { 
}
.lock-header { 
  overflow-y: auto; 
  max-height: 300px; 
  width:300px;
  padding:0;
}
.lock-header thead>tr:first-child>th { 
  background-color: rgba(240,240,240,0.8);
  z-index:1;
  position: sticky; 
  top: 0; 
}
.lock-header>table { 
  border-collapse: collapse; 
  width: 100%; 
}
.lock-header tfoot td { 
  background-color: rgba(240,240,240,1);
  z-index:99;
  position: sticky; 
  bottom: 0; 
}

</style>
<div >
  <table>
    <thead>
      <tr>
        <th>Column 1</th>
        <th>Column 2</th>
        <th>Column 3</th>
        <th>Column 4</th>
        <th>Column 5</th>
        <th>Column 6</th>
        <th>Column 7</th>
        <th>Column 8</th>
        <th>Column 9</th>
        <th>Column 10</th>
        <th>Column 11</th>
        <th>Column 12</th>
        <th>Column 13</th>
        <th>Column 14</th>
        <th>Column 15</th>
        <th>Column 16</th>
        <th>Column 17</th>
        <th>Column 18</th>
        <th>Column 19</th>
        <th>Column 20</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
      <tr>
        <td>Some fake row</td>
      </tr>
    </tbody>
  </table>
</div>

is this what you want ? I tried it on codepen and it works

CodePudding user response:

This can't be done with just CSS. The sticky position requires the initial overflow value on parent containers, you will have to use JS to stick the header row.

  • Related