<table> 带有固定的 <thead> 和可滚动的 <tbody>

新手上路,请多包涵

我已经浏览了这里的问题和互联网上的文章,但还没有找到满足我要求的解决方案。所以现在在 2017 年,有没有一种优雅的方式来拥有一个 <table> 这将:

  1. 用html+css写(无js)
  2. 有固定的标题(不可滚动;不粘)
  3. 可滚动 <tbody> (滚动条可能始终可见)
  4. 标题和正文将正确处理调整大小,并且不会弄乱 <thead> 列和 <tbody> 列的对齐
  5. 不会使用嵌套表或单独的表作为标题

原文由 Dmitry Stril 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

该解决方案满足所有 5 个要求:

 table {
  width: 100%;
}

table, td {
  border-collapse: collapse;
  border: 1px solid #000;
}

thead {
  display: table; /* to take the same width as tr */
  width: calc(100% - 17px); /* - 17px because of the scrollbar width */
}

tbody {
  display: block; /* to enable vertical scrolling */
  max-height: 200px; /* e.g. */
  overflow-y: scroll; /* keeps the scrollbar even if it doesn't need it; display purpose */
}

th, td {
  width: 33.33%; /* to enable "word-break: break-all" */
  padding: 5px;
  word-break: break-all; /* 4. */
}

tr {
  display: table; /* display purpose; th's border */
  width: 100%;
  box-sizing: border-box; /* because of the border (Chrome needs this line, but not FF) */
}

td {
  text-align: center;
  border-bottom: none;
  border-left: none;
}
 <table>
  <thead>
    <tr>
      <th>Table Header 1</th>
      <th>Table Header 2</th>
      <th>Table Header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data1111111111111111111111111</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data2222222222222222222222222</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data3333333333333333333333333</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
    <tr>
      <td>Data</td>
      <td>Data</td>
      <td>Data</td>
    </tr>
  </tbody>
</table>

原文由 VXp 发布,翻译遵循 CC BY-SA 4.0 许可协议

铬,FF,边缘

最简单的解决方案是使用 th { position: sticky; top: 0; }

 /* JUST COMMON TABLE STYLES... */
table { border-collapse: collapse; width: 100%; }
th, td { background: #fff; padding: 8px 16px; }

.tableFixHead {
  overflow: auto;
  height: 100px;
}

.tableFixHead thead th {
  position: sticky;
  top: 0;
}
 <div class="tableFixHead">
  <table>
    <thead>
      <tr><th>TH 1</th><th>TH 2</th></tr>
    </thead>
    <tbody>
      <tr><td>A1</td><td>A2</td></tr>
      <tr><td>B1</td><td>B2</td></tr>
      <tr><td>C1</td><td>C2</td></tr>
      <tr><td>D1</td><td>D2</td></tr>
      <tr><td>E1</td><td>E2</td></tr>
    </tbody>
  </table>
</div>

IE11

为了草率地支持 IE11(截至 2018 年 10 月 市场份额为 2.5% ),有点参差不齐但至少 TH s 在最上面 - 你可以添加这个 JavaScript:

 function isIE() {
  return navigator.userAgent.indexOf('MSIE') > -1 || navigator.appVersion.indexOf('Trident/') > -1
}

if (isIE()) {

  // Fix table head
  function tableFixHead(ths) {
    var sT = this.scrollTop;
    [].forEach.call(ths, function(th) {
      th.style.transform = "translateY(" + sT + "px)";
    });
  }

  [].forEach.call(document.querySelectorAll(".tableFixHead"), function(el) {
    var ths = el.querySelectorAll("thead th");
    el.addEventListener("scroll", tableFixHead.bind(el, ths));
  });

}

这将(因为 IE 忽略 sticky 位置)使用 transform translateY 定位 TH 元素。

PS: 上面的 JS(没有包装 if 声明)也适用于所有其他常绿浏览器 - 万一 position: sticky; 不符合你的需要……

原文由 Roko C. Buljan 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题