在 <table> 元素上使用 Firefox 的 sticky 定位属性

5
新的position属性值让我感到非常困惑...很多搜索结果都提供了javascript/jQuery(JavaScript框架)的解决方案。
在下面的例子中,我有一个带有thead和tbody的表格。
无论我做什么,都不能实现所需的结果。所需的结果是thead粘在表格上。"粘"的意思是当元素不在视图中时,它会以某种position:fixed的方式固定在屏幕上。我尝试过:
  • display:inline/block/inline-block;
  • th元素position:sticky(th元素是thead元素内部的tr元素的一部分)
  • 混合使用display:inline/block等(display属性的值)
我只是找不到如何在Firefox(支持)中实现这个"粘"的效果。
有任何解决方案吗?
(因为position:sticky仍然是一个实验性API,不应在生产站点中使用,详情请参见http://developer.mozilla.org/en/docs/Web/CSS/position

table {
  background-color: rgba(241, 31, 0, 0.3);
  width: 100%;
}
thead {
  background-color: rgba(241, 0, 241, 0.3);
  position: -webkit-sticky;
  position: sticky;
}
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>


@Gaurav Aggarwal:请勿在版主删除评论后重新发布。 - BoltClock
所以,根据标题,您只想将表元素固定,是吗?如果是这样,那应该可以正常工作,表格在这方面与任何其他块级元素没有区别。但是您的代码说您正在将position sticky应用于thead而不是整个表格。那么到底是哪一个呢?还有谁承诺了什么? - BoltClock
@GCyrillus 非常感谢您!!! BoltBlock 和另一个用户一直在推翻这个问题。所以如果我错了,请纠正我... caniuse.com 等网站说 position:sticky 是有效的是错误的。 - user4431269
@GCyrillus,您的解决方案适用于屏幕上的多个表元素。但我不明白的是,我知道它会触发 top:0px;,这通常需要触发粘性吗? - user4431269
1
是的,它是用来告诉滚动条在哪里应该保持静止的。因此它可以移动一点,但在某个点上保持静止。 - G-Cyrillus
显示剩余11条评论
3个回答

7

火狐浏览器似乎还不支持在表格子元素上使用“sticky”。

一个解决方法是将table设置为block,然后将theadtbodytfoot设置为display:table;,这样其中一个就可以粘住了。

不幸的是,这会破坏表格布局并将表格拆分成几个表格.. :(

您还需要设置粘性生效的坐标 http://codepen.io/gc-nomade/pen/reoExq。不太理想 :(

CSS基础代码如下:

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>


4
另一种方法是使用CSS3来翻译表头单元格。这种方法需要JavaScript,并且在所有现代浏览器中都可以使用,但由于它翻译的是表格单元格,因此某些原因边框不会被包括在内(demo)。
此外,这个CSS样式必须包含在被翻译的单元格上才能显示背景颜色。
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)");
});

1
转换和thead单元格的背景和边框似乎确实有点问题。background-clip可以帮助解决,box-shadow可以加强它:测试http://jsfiddle.net/bfocjv9s/8/。 - G-Cyrillus
这段JavaScript代码片段特别适用于火狐浏览器的固定表头列。火狐浏览器的怪异模式=开启? - Oleksii Kyslytsyn

1

2018年第一季度更新

position: sticky现在已经在稳定版Firefox 59中上线。下面链接的示例在Firefox中也可以正常工作。


我知道您特别要求position: sticky在Firefox中的兼容性,但不幸的是它在Firefox中对内部表格元素的样式效果未定义:

引用自https://developer.mozilla.org/en/docs/Web/CSS/position

相对定位(position:relative)对于表格元素(table-*-group、table-row、table-column、table-cell和table-caption)的效果未定义。

‘position: sticky’对表格元素的影响与‘position: relative’相同。

话虽如此,position: sticky即将登陆Chrome稳定通道(目前正在Canary中,并且有一篇developer.google.com的博客文章介绍了它)。他们的实现在thead上可以很好地工作,解决了我长期以来固定表头的问题,因为所有其他解决方案在需要调整表格/单元格宽度时都会失败。

我创建了一个fiddle来测试粘性定位。在所有Firefox渠道上,这没有任何效果。

我希望由于Chrome中更完整的实现,position:sticky现在获得了更多的关注,它将再次引起对sticky内部表支持不足的讨论。

Firefox的Bugzilla上也有一个错误报告: https://bugzilla.mozilla.org/show_bug.cgi?id=975644


1
在规范中没有提到将sticky属性视为表格元素的相对属性。 - 18C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接