Willem de Wit
Willem de Wit

Reputation: 8742

Position sticky on thead

As you might know, position: sticky; has landed in Webkit (demo). So far I can see this only works within the parent element. But I'd like to know if I can use this in a scrolling div with a table.

So it needs to 'listen' on the scrolling event of the div, not the table.

I know I can do this with javascript and absolute positioning, but I was wondering if the sticky-positioning would support this.

Upvotes: 66

Views: 129335

Answers (7)

bioform
bioform

Reputation: 148

If you need sticky header for chrome only then you can set position: sticky; top: some_value (top property is mandatory) for td element in a thead element.

See:

<table border=1>
  <thead>
    <tr>
      <td style='position: sticky; top: -1px;background: red'>Sticky Column</td>
      <td>Simple column</td>
    </tr>
  </thead>

table with a stiky header

Upvotes: 14

Evolve
Evolve

Reputation: 9229

Position sticky on thead th works in 2018!

table { border-spacing: 1px; }
th, td { background: white; color: black; border: 1px solid black; }
thead th { position: sticky; top: 0; }
<table>
    <thead>
        <tr> <th>column 1 <th>column 2 <th>column 3 <th>column 4
    </thead>
    <tbody>
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
        <tr> <td>data <td>data <td>data <td>data
    </tbody>
</table>

Also, if you have multiple rows in <thead>, you can select the first one to remain sticky:

thead tr:first-child th { position: sticky; top: 0; }

As of March 2018 support is pretty much there across modern browsers ref: https://caniuse.com/#feat=css-sticky

Credit goes to @ctf0 for this one (ref comment made 3 Dec 2017)

Upvotes: 133

Martin Cremer
Martin Cremer

Reputation: 5592

If it ain't working, adding a z-index to thead or th might help.

Upvotes: 0

Shahram Alemzadeh
Shahram Alemzadeh

Reputation: 1146

Setting the position:sticky for the thead is enough, no need to set it for th :

table.StickyHeader thead {
    position: sticky;
    top: 0px;
}

Tested in:

Edge 105.0.1343.42 , Firefox 105.0 , Chrome 105.0.5195.127 , Opera 91.0.4516.16

But, Firefox can not render borders of th when position of thead is set to sticky and th has background-color:

table.StickyHeader th {
    border: 1px solid black;
    padding: 5px;
    background-color: gold;
    text-align: center;
}

Firefox

Edge, Chrome, Opera

Upvotes: 7

lucasvm1980
lucasvm1980

Reputation: 682

Caution:

position:sticky doesn't work anymore on Google Chrome in 2019, try to use fixed instead or display:inline-block

Upvotes: -1

Willem de Wit
Willem de Wit

Reputation: 8742

As it turns out it position: sticky only works in the window and not in a scrolling div.

I created a test-case with a very long table with a table header:

h1 {
  font-size: 18px;
  font-weight: bold;
  margin: 10px 0;
}

div.testTable {
  height: 200px;
  overflow: auto;
}

table.stickyHead thead {
  position: -webkit-sticky;
  top: 0px;
  background: grey;
}

table.stickyHead td,
table.stickyHead th {
  padding: 2px 3px;
}
<h1>Position sticky</h1>
<div class="testTable">
  <table class="stickyHead">
    <thead>
      <tr>
        <th>column 1</th>
        <th>column 2</th>
        <th>column 3</th>
        <th>column 4</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
    </tbody>
  </table>
</div>

As you can see, if you remove the overflow from the wrapper and make your window not so tall, the table-head is sticking to the top of the window. I doesn't apply to the wrapping div even if you make give the div position: relative

Upvotes: 4

czerny
czerny

Reputation: 16692

position: sticky doesn't work with table elements (as long as their display attribute starts with table-) since tables are not part of specification:

Other kinds of layout, such as tables, "floating" boxes, ruby annotations, grid layouts, columns and basic handling of normal "flow" content, are described in other modules.


Edit: As Jul 2019 according to https://caniuse.com/#feat=css-sticky Firefox supports this feature and Chrome has at least support for <th> tag.

Upvotes: 11

Related Questions