在Chrome浏览器中实现纯CSS粘性表头

70
我有以下的 Sass 代码片段,我希望在表格滚动时 <thead> 元素浮动。在 Safari 中这个功能正常运作,但在 Chrome Version 58.0.3029.110 (64-bit) 中无法实现。我知道 Chrome 曾经断断续续地支持过 sticky,现在也支持了,但这是最终版本吗?这是一个 Chrome 的 Bug 吗?还是说我需要另一种解决方案?(我更喜欢 CSS 的方法,因为它更加高效。)
.table {
  thead {
    background: white;
    position: sticky;
    top: 0;
    z-index: 10;
  }
}

4
根据浏览器的支持情况,我建议使用“fixed”代替“sticky”。据我所知,目前并不是所有浏览器都支持“sticky”。 - Michael
2
相关的Chromium Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=702927 - styfle
4个回答

86

在Chrome浏览器中,position: sticky不能与某些表格元素(如thead/tr)一起使用。您可以将sticky属性应用于需要保持定位的td/ths元素,例如:

```css td { position: sticky; /* 其他样式 */ } ```
.table {
  thead tr:nth-child(1) th{
    background: white;
    position: sticky;
    top: 0;
    z-index: 10;
  }
}

这个也可以工作。

.table {
    position: sticky;
    top: 0;
    z-index: 10;
}

你可以把头部放到一个单独的布局中。例如:

<table class="table">
    <thead>
    <tr>
        <th>1</th>
        <th>2</th>
        <th>3</th>
        <th>4</th>
    </tr>
    </thead>
</table>
<table>
    <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>
</table>

22
仅当列的宽度都相等时,才可以使用单独布局选项。 - Rick Viscomi
63
值得注意的是,如果表格包含在具有 overflow: autooverflow-x: auto 属性的元素内部,则此解决方法将无效。这种情况通常出现在使用 Bootstrap 的 .table-responsive 类包装表格时。 - FiniteLooper
2
我同意Rick Viscomi的观点,即仅当所有列的宽度相同时,单独的布局选项才是可行的,并且如果在表格之后还有其他内容,则该解决方案也不是没有缺点,因为整个内容的粘性表格甚至在第二个带有内容的表格结束后仍然存在,因此在大多数情况下无法使用。可以在jfiddle上查看以下地址的示例:https://jsfiddle.net/eg6s4097/1/,其中包括所有提到的缺点。 - willy wonka
1
@CBarr,我也遇到了这个问题。如果需要将其包装在table-responsive类中,您有任何解决方案吗? - misteroptimist
现在你可以直接在Chrome中将position: sticky添加到thead - Leponzo
显示剩余2条评论

43

对于那些仍在寻找解决方案并对已接受的方案不满意的人来说:

1) 在th元素上使用sticky-top类。

2) 使用自己的类。

th.sticky-header {
  position: sticky;
  top: 0;
  z-index: 10;
  /*To not have transparent background.
  background-color: white;*/
}
<table class="table">
  <thead>
    <tr>
      <th class="sticky-header">1</th>
      <th class="sticky-header">2</th>
      <th class="sticky-header">3</th>
      <th class="sticky-header">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>
  </tbody>
</table>


5
如果thead中有两行(或更多)表头行,怎么处理? - Jivan
@Jivan 在第二个thead上添加一个类,将'top'属性设置为第一个表头的高度。这不是动态的,您必须知道第一个thead的高度。 - Jon
1
谢谢!正如Cbarr所说:“值得注意的是,如果表格包含在具有overflow: auto或overflow-x: auto属性的元素中,则此方法将无法正常工作。这种情况发生在您将表格包装在Bootstrap的.table-responsive类中。” 这正是我的情况,而你Tomsgu的答案解决了这个问题! - Dimitri

8
您应该将粘性定位设置在表格单元格(table-cell)而不是行(table-row)上,以实现头部固定的效果。
.td.header {
  position: sticky;
  top:0px;
}

请查看这个 JSFiddle ,里面有一个简单的示例。


2

https://jsfiddle.net/y9cwnb81/4/

div.table {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr auto;

  grid-template-areas:
    "header header header"
    "content content content";
}

.header {
  grid: 1fr/1fr;
}

.content {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto;
  grid-area: content;
  height: 200px;
  overflow-y: scroll;
}

.content div {
  grid: auto-flow 1fr / repeat(auto-fill);
}

<!-- Here is the table code -->

<div class="table">
  <div class="header">Name</div>
  <div class="header">Color</div>
  <div class="header">Description</div>
  <div class="content">
    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd,mas, da,msnd asndm,asndm,asndbansbdansmbdmnasbd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>

    <div>Apple</div>
    <div>Red</div>
    <div>These are red asd.</div>
  </div>
</div>

这是一个使用CSS GRID实现仅使用CSS具有粘性标头的示例,无需JavaScript。

这是一个具有固定高度和“overflow-y: scroll”的网格。它没有使用“position: sticky”(因此标题不会“粘”在视口顶部)。尽管如此,这是一个有用的答案,可以适应使用“position: sticky”。谢谢! - Patrick McElhaney
1
这个不按预期工作,因为标题也在水平方向上固定了。 - nights

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