Position: sticky (firefox) on a <table> element

江枫思渺然 提交于 2019-11-30 21:35:36

Firefox seems not to allow yet 'sticky' on table childs elements.

a workaround would be to set table as block, then thead, tbody, tfoot to display:table; so one of them can be sticked.

unfortunately this breaks the table-layout and split table into few tables .. :(

you also need to set coordonates where sticky comes in action http://codepen.io/gc-nomade/pen/reoExq . not the best :(

CSS base would be like:

table {
  display: block;
}

thead {
  position: sticky;
  top: 0px;  /* trigger sticky when reaches coordonates */
}

thead, tbody, tfoot {
  display: table;
  width: 100%;
}

table {
  background-color: rgba(241, 31, 0, 0.3);
  width: 100%;
  margin-top: 1em;
  position: static;
  display: block;
}
thead {
  display: table;
  width: 100%;
  background-color: rgba(241, 0, 241, 0.3);
  position: sticky;
  top: 0px;
  /* trigger sticky when reaches coordonates */
}
tbody {
  display: table;
  width: 100%;
}
th {} tbody td:nth-child(2) {
  height: 200px;
}
<table>
  <thead>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
  </tbody>
</table>
<table>
  <thead>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
  </tbody>
</table>
<table>
  <thead>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
  </tbody>
</table>
<table>
  <thead>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
    </tr>
  </tbody>
</table>

Another method is to use css3 to translate the header cells. This method does require javascript and will work in all modern browsers, but because it translates the table cell, the border does not get included for some reason (demo)

Also, this css is necessary to include a background color on the translated cells

thead th,
caption {
  background: #fff;
}

jQuery

var $win = $(window),
  $table = $('table'),
  $thead = $table.children('thead'),
  $tfoot = $table.children('tfoot'),
  $caption = $table.children('caption'),
  $cells = $thead.children().children().add($caption);

$win.on('scroll', function() {
  var bottom = $table.position().top +
        $table.height() -
        $thead.height() -
        ($tfoot.height() || 0),
    delta = $win.scrollTop() -
        $thead.offset().top +
        $caption.outerHeight(),
    // include border thickness (minus 2)
    vertPos = (delta < 0 || delta > bottom ? 0 : delta - 2);
  $cells.css("transform", "translate(0px," + vertPos + "px)");
});

Update Q1 2018

position: sticky has now landed in stable Firefox 59. The fiddle linked below now works unchanged in Firefox as well.


I know you specifically asked for Firefox compatibility of position: sticky, but unfortunately its styling effect in Firefox is not defined on inner table elements:

Quoting from https://developer.mozilla.org/en/docs/Web/CSS/position

The effect of position:relative on table-*-group, table-row, table-column, table-cell, and table-caption elements is undefined.

The effect of ‘position: sticky’ on table elements is the same as for ‘position: relative’.

That being said, position: sticky is about to land in Chrome Stable channel (it is in Canary at the time of writing and there's a developer.google.com blog post about it). Their implementation does work fine on thead, solving my own long-standing problem of sticky theads as all other solutions fail when you need to resize the table/cell widths.

I've created a fiddle to test the sticky positioning. On all channels of Firefox, this has no effect.

My hope is that position: sticky now gains tractions due to the more complete implementation in Chrome, it will stir discussions again on the lacking inner table support of sticky.

There's also a bug report on Firefox' Bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=975644

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!