在纯CSS中实现固定表头和固定列的表格

132

我需要创建一个带有固定头部和第一列的HTML表格(或类似外观的表格)。

迄今为止,我看到的每个解决方案都使用JavaScript或jQuery来设置scrollTop/scrollLeft,但在移动浏览器上不够流畅,因此我正在寻找纯CSS解决方案。

我在这里找到了一个解决固定列的方案:jsfiddle.net/C8Dtf/20/,但我不知道如何增强它以使头部也固定。

我希望它能在Webkit浏览器上运行或使用一些CSS3功能,但我再次强调,我不想使用Javascript进行滚动。

编辑: 这是我想要实现的行为示例:https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html


我目前没有看到 <html> 带有固定标题 <thead> 的 <table> 与 CSS-3 级别有什么关系。你还有什么其他想法?你迄今为止尝试了什么? - Milche Patern
我尝试将复杂的“position”行为应用于行和单元格,但我不太明白它在哪里适用或不适用。 - panfil
2
这个答案可能会对你有所帮助 https://dev59.com/RmUq5IYBdhLWcg3wC8Lx#22801367 - Garry
22个回答

207

position: sticky属性在现代版本的Chrome、Firefox和Edge浏览器中支持同时粘贴到顶部和侧边。这可以与具有overflow: scroll属性的

结合使用,以在页面上的任何位置放置具有固定标题的表格。

将您的表格放在一个容器中:

<div class="container">
  <table></table>
</div>

使用overflow: scroll在您的容器上启用滚动:

div.container {
  overflow: scroll;
}

正如Dagmar在评论中指出的那样,容器还需要一个max-width和一个max-height

使用position: sticky将表格单元格粘附到边缘,并使用toprightleft选择要粘附到哪个边缘:

thead th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
}

tbody th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
}

正如MarredCheese在评论中提到的,如果您的第一列包含<td>元素而不是<th>元素,则可以在CSS中使用tbody td:first-child而不是tbody th

要使第一列中的标题固定在左侧,请使用:

thead th:first-child {
  left: 0;
  z-index: 1;
}

/* Use overflow:scroll on your container to enable scrolling: */

div {
  max-width: 400px;
  max-height: 150px;
  overflow: scroll;
}


/* Use position: sticky to have it stick to the edge
 * and top, right, or left to choose which edge to stick to: */

thead th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
}

tbody th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
}


/* To have the header in the first column stick to the left: */

thead th:first-child {
  left: 0;
  z-index: 2;
}


/* Just to display it nicely: */

thead th {
  background: #000;
  color: #FFF;
  /* Ensure this stays above the emulated border right in tbody th {}: */
  z-index: 1;
}

tbody th {
  background: #FFF;
  border-right: 1px solid #CCC;
  /* Browsers tend to drop borders on sticky elements, so we emulate the border-right using a box-shadow to ensure it stays: */
  box-shadow: 1px 0 0 0 #ccc;
}

table {
  border-collapse: collapse;
}

td,
th {
  padding: 0.5em;
}
<div>
  <table>
    <thead>
      <tr>
        <th></th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
    </tbody>
  </table>
</div>

https://jsfiddle.net/qwubvg9m/1/


25
这似乎是最好的答案。 - user1190132
9
如果你知道第一列的宽度,你可以在第二列的单元格中使用position: sticky属性,并将left值设为第一列的width值:https://jsfiddle.net/wvypo83c/794/ - Matthew Schlachter
4
这个回答证明了读到底部是值得的! - mlerley
6
容器必须设置最大宽度和最大高度,否则此方法无法生效。 - Dagmar
13
这个答案就像一座灯塔,通过那些在SO和整个网络上出现的令人困惑但却得到意外投票的过于复杂、浪费时间的回答中指引我们回家。请注意,如果你的第一列包含<td>元素而不是<th>元素,则可以在CSS中使用tbody td:first-child替代tbody th - MarredCheese
显示剩余15条评论

45
现在,使用CSS的position: sticky属性就可以实现这一点了。以下是一个代码片段:(jsFiddle: https://jsfiddle.net/hbqzdzdt/5/)

.grid-container {
  display: grid; /* This is a (hacky) way to make the .grid element size to fit its content */
  overflow: auto;
  height: 300px;
  width: 600px;
}
.grid {
  display: flex;
  flex-wrap: nowrap;
}
.grid-col {
  width: 150px;
  min-width: 150px;
}

.grid-item--header {
  height: 100px;
  min-height: 100px;
  position: sticky;
  position: -webkit-sticky;
  background: white;
  top: 0;
}

.grid-col--fixed-left {
  position: sticky;
  left: 0;
  z-index: 9998;
  background: white;
}
.grid-col--fixed-right {
  position: sticky;
  right: 0;
  z-index: 9998;
  background: white;
}

.grid-item {
  height: 50px;
  border: 1px solid gray;
}
<div class="grid-container">
  <div class="grid">
    <div class="grid-col grid-col--fixed-left">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
      <div class="grid-item">
        <p>Hello</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
      <div class="grid-item">
        <p>P</p>
      </div>
    </div>

    <div class="grid-col grid-col--fixed-right">
      <div class="grid-item grid-item--header">
        <p>HEAD</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
      <div class="grid-item">
        <p>9</p>
      </div>
    </div>

  </div>
</div>

关于兼容性。它可以在所有主流浏览器中工作,但不支持IE。有一个用于position: sticky的polyfill,但我从未尝试过。


2
这太棒了,喜欢它! - user8494897
4
有没有使用<table>标签而不是<div>标签来实现这一点的方法? - Andreas
1
如果您正在开发一个需要循环遍历记录以打印此表的应用程序,我认为这不会有良好的性能,因为对于表中的每一列,您都必须循环遍历整个记录数组。这个HTML是逐列工作的。 - igasparetto
@igasparetto 实际上,您可以将行/列的顺序反过来排列,解决方案仍然有效。如果我有时间,稍后我可以创建一个以行->列排序的网格片段。 - Alvaro
4
我建议不要在没有使用<table>和相关标签的情况下显示表格数据。这种方式违反了HTML的预期用法,存在许多问题,包括可访问性问题。参见:https://www.w3.org/WAI/tutorials/tables/。 - Ben Morris
最佳解决方案。感谢@Alvaro。 - Zohaib Ijaz

15

这不是一件容易的事情。

下面链接是一个工作演示:

根据lanoxx评论更新的链接

http://jsfiddle.net/C8Dtf/366/

只需记住添加这些内容:

<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/extras/FixedColumns/media/js/FixedColumns.js"></script>

我不见得有任何其他实现这个的方法,特别是仅使用 CSS 是不可能的。

这需要阅读很多内容。希望这可以帮到你 :)


要关闭过滤器,请使用: "bFilter": false - lanoxx
6
只用 CSS 是有可能实现这个的。虽然不太容易,但是可以做到。 - Jimmy T.
从大约10个解决方案中,这是唯一有效的一个。顺便说一下,要删除“显示1到57个条目中的57个”,请在.dataTable()调用中添加"bInfo": false - hansaplast
datatables == "棒极了" - But those new buttons though..
因为这个解决方案很糟糕,所以被踩了。thead在自己的表格中,不受td元素更改的影响,因此如果单元格文本很长,th宽度将不会相应调整。 - vsync
显示剩余2条评论

15
所有这些建议都很棒,但它们只修复了标题或列中的一个,而不是两者都修复,或者它们使用JavaScript。原因 - 我不相信纯CSS可以做到这一点。原因在于:
如果可能的话,您需要将几个可滚动的div嵌套到彼此之内,并且每个div都有不同的滚动方向。然后,您需要将表格分为三部分 - 固定标题、固定列和其他数据。
好的。但现在问题来了 - 当您滚动时,您可以让其中一个保持不动,但另一个嵌套在第一个滚动区域内,并且因此可能被滚动而看不见,所以无法固定在屏幕上。您可能会说“啊哈”,但我可以通过绝对或固定位置来解决问题 - 不行。一旦你这样做,你就失去了滚动该容器的能力。这是个鸡生蛋还是蛋生鸡的局面-你不能同时拥有二者,它们互相抵消。
我认为唯一的解决方案是通过JavaScript。您需要完全分离这三个元素,并通过JavaScript保持它们的位置同步。本页面中的其他帖子中有很好的例子。这个也值得一看: http://tympanus.net/codrops/2014/01/09/sticky-table-headers-columns/

除非未来版本的CSS覆盖了这种行为,否则应将此作为对该问题的答案接受。 - Greg

9

我在 jsfiddle 中进行了一些更改。这可能是您想要做的。

http://jsfiddle.net/C8Dtf/81/

我已经硬编码了标题,如下所示:

<table id="left_table" class="freeze_table">
    <tr class='tblTitle'>
         <th>Title 1</th>
         <th>Title 2</th>
    </tr>
</table>

我还添加了一些样式。

.tblTitle{
   position:absolute;
    top:0px;
    margin-bottom:30px;
    background:lightblue;
}
td, th{
    padding:5px;
    height:40px;
    width:40px;
    font-size:14px;
}

Hope this is what you want :)


1
我需要右侧表格的标题与其内容一起滚动。 - panfil
这是URL链接:http://jsfiddle.net/C8Dtf/84/。您只需要调整右侧表格的样式以使两个表格对齐即可。 - Phillip-juan
不好意思,您似乎没有完全理解我的意思。我需要右侧表格的标题固定在顶部,这样当表格上下滚动时,标题仍然可见,但是当表格左右滚动时,标题必须左右滚动,但仍然固定在顶部。非常抱歉我的英语水平不好。 - panfil
想要在垂直滚动时固定右侧表格的标题,而在水平滚动时滚动吗? - Phillip-juan
这是我想要实现的行为示例:http://datatables.net/release-datatables/extras/FixedColumns/css_size.html - panfil
尽管右侧表格的标题不会滚动,但这仍然是一个非常酷的解决方案。特别是它是唯一允许使用 table-layout: auto 的解决方案。对于较小的表格,可以通过滚动监听器解决标题问题,这里有一个使用React的示例(没有完全样式化,所以有点丑...) - cazzer

9
一个仅使用 CSS 的示例:

.table {
  table-layout: fixed;
  width: 500px;
  border-collapse: collapse;
}

.header th {
  font-family: Calibri;
  font-size: small;
  font-weight: lighter;
  border-left: 1px solid #000;
  background: #d0d0d0;
}

.body_panel {
  display: inline-block;
  width: 520px;
  height: 300px;
  overflow-y: scroll;
}

.body tr {
  border-bottom: 1px solid #d0d0d0;
}

.body td {
  border-left: 1px solid #d0d0d0;
  padding-left: 3px;
  font-family: Calibri;
  font-size: small;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
<body>

  <table class="table">

    <thead class="header">

      <tr>
        <th style="width:20%;">teste</th>
        <th style="width:30%;">teste 2</th>
        <th style="width:50%;">teste 3</th>
      </tr>

    </thead>
  </table>

  <div class="body_panel">

    <table class="table">
      <tbody class="body">

        <tr>
          <td style="width:20%;">asbkj k kajsb ksb kabkb</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

        <tr>
          <td style="width:20%;">2</td>
          <td style="width:30%;">2</td>
          <td style="width:50%;">3</td>
        </tr>

      </tbody>
    </table>

  </div>

</body>


3
我不仅需要修复标题固定,还需要修复第一列。 - panfil
这个例子展示了一种使用两个HTML表格的方法:一个表格仅呈现标题;第二个表格仅呈现行,但是在div中进行。正是div允许行滚动而标题保持不变。这种方法适合我的需求。 - David Tansey
如果还有水平滚动,您需要一些JS来同步表格的滚动位置。 - Zoltán Tamási

4
我发现 Paul O'Brien 提供了一种解决方法,这是一个非常好的方案,我想分享链接: https://codepen.io/paulobrien/pen/LBrMxa 我移除了页脚的样式:
html {
  box-sizing: border-box;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}
.intro {
  max-width: 1280px;
  margin: 1em auto;
}
.table-scroll {
  position: relative;
  width:100%;
  z-index: 1;
  margin: auto;
  overflow: auto;
  height: 350px;
}
.table-scroll table {
  width: 100%;
  min-width: 1280px;
  margin: auto;
  border-collapse: separate;
  border-spacing: 0;
}
.table-wrap {
  position: relative;
}
.table-scroll th,
.table-scroll td {
  padding: 5px 10px;
  border: 1px solid #000;
}
.table-scroll thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
}

th:first-child {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 2;
  background: #ccc;
}
thead th:first-child {
  z-index: 5;
}

4
为了同时固定表头和列,您可以使用以下插件:

2019年7月更新

最近出现了一种基于CSS属性position: sticky;纯CSS解决方案(有关详细信息,请参见此处),应用于每个TH项(而不是它们的父容器)。


1
第一个链接已经失效了。第二个链接使用了jQuery。 - PussInBoots
已更新的回答,移除了失效的链接。 - Luca Detomi

2
我最近需要创建一个带有固定标题组和固定第一列的解决方案。我将表格分成了几个div,并使用jquery来捕获窗口滚动。 http://jsfiddle.net/TinT/EzXub/2346/
var prevTop = 0;
var prevLeft = 0;

$(window).scroll(function(event){
  var currentTop = $(this).scrollTop();
  var currentLeft = $(this).scrollLeft();

  if(prevLeft !== currentLeft) {
    prevLeft = currentLeft;
    $('.header').css({'left': -$(this).scrollLeft()})
  }
  if(prevTop !== currentTop) {
    prevTop = currentTop;
    $('.leftCol').css({'top': -$(this).scrollTop() + 40})
  }
});

1
现有的答案适合大多数人,但对于那些想要在固定标题下方和第一列(固定列)右侧添加阴影的人,这里提供一个有效的示例(纯CSS):

http://jsbin.com/nayifepaxo/1/edit?html,output

使这个工作起来的主要技巧是使用::after为每个tr中的第一个td添加右侧阴影:

tr td:first-child:after {
  box-shadow: 15px 0 15px -15px rgba(0, 0, 0, 0.05) inset;
  content: "";
  position:absolute;
  top:0;
  bottom:0;
  right:-15px;
  width:15px;
}

花了我一段时间(太长了……)才将所有内容都搞定,所以我想分享给那些处于类似情况的人。

你是基于别人的答案并添加了阴影吗? - PussInBoots

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