是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。

我希望能够滚动表的内容,但总是能够在顶部看到列标题。


当前回答

不知怎的,我以Position:Sticky在我的案例中工作得很好:

table{ width: 100%; border: collapse; } th{ position: sticky; top: 0px; border: 1px solid black; background: #ff5722; color: #f5f5f5; font-weight: 600; } td{ background: #d3d3d3; border: 1px solid black; color: #f5f5f5; font-weight: 600; } div{ height: 150px overflow: auto; width: 100% } <div> <table> <thead> <tr> <th>header 1</th> <th>header 2</th> <th>header 3</th> <th>header 4</th> <th>header 5</th> <th>header 6</th> <th>header 7</th> </tr> </thead> <tbody> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> <tr> <td>data 1</td> <td>data 2</td> <td>data 3</td> <td>data 4</td> <td>data 5</td> <td>data 6</td> <td>data 7</td> </tr> </tbody> </table> </div>

其他回答

简单的jQuery插件

这是Mahes解的一个变种。你可以像这样调用它$('table#foo').scrollableTable();

这个想法是:

将head和tbody分割为单独的表元素 使它们的单元格宽度再次匹配 将第二个表包装在div.scrollable中 使用CSS使div.scrollable实际滚动

CSS可以是:

div.scrollable { height: 300px; overflow-y: scroll;}

警告

显然,拆分这些表会降低标记的语义性。我不确定这对可访问性有什么影响。 这个插件不处理页脚,多个页眉等。 我只在Chrome 20版本中测试过。

也就是说,它符合我的目的,你可以自由地使用和修改它。

下面是插件:

jQuery.fn.scrollableTable = function () {
  var $newTable, $oldTable, $scrollableDiv, originalWidths;
  $oldTable = $(this);

  // Once the tables are split, their cell widths may change. 
  // Grab these so we can make the two tables match again.
  originalWidths = $oldTable.find('tr:first td').map(function() {
    return $(this).width();
  });

  $newTable = $oldTable.clone();
  $oldTable.find('tbody').remove();
  $newTable.find('thead').remove();

  $.each([$oldTable, $newTable], function(index, $table) {
    $table.find('tr:first td').each(function(i) {
      $(this).width(originalWidths[i]);
    });
  });

  $scrollableDiv = $('<div/>').addClass('scrollable');
  $newTable.insertAfter($oldTable).wrap($scrollableDiv);
};

所有从CSS规范之外解决这个问题的尝试都是我们真正想要的:按照THEAD的隐含承诺交付。

这个冻结表头的问题长期以来一直是HTML/CSS中的一个开放性问题。

在理想的情况下,应该有一个纯css解决方案来解决这个问题。不幸的是,似乎没有一个合适的。

相关标准-关于此主题的讨论包括:

粘性定位提案网址:http://lists.w3.org/Archives/Public/www-style/2012Jun/0627.html 请在阿特金斯提出的“位置-根”、“位置-包含”或“位置-限制”的建议中打上标签:http://www.xanthir.com/blog/b48H0

更新:Firefox的发货位置:粘在版本32。每个人都会赢!

我发现这个解决方案-移动标题行在表上面的表与数据:

<html> <head> <title>Fixed header</title> <style> table td {width:75px;} </style> </head> <body> <div style="height:auto; width:350px; overflow:auto"> <table border="1"> <tr> <td>header 1</td> <td>header 2</td> <td>header 3</td> </tr> </table> </div> <div style="height:50px; width:350px; overflow:auto"> <table border="1"> <tr> <td>row 1 col 1</td> <td>row 1 col 2</td> <td>row 1 col 3</td> </tr> <tr> <td>row 2 col 1</td> <td>row 2 col 2</td> <td>row 2 col 3</td> </tr> <tr> <td>row 3 col 1</td> <td>row 3 col 2</td> <td>row 3 col 3</td> </tr> <tr> <td>row 4 col 1</td> <td>row 4 col 2</td> <td>row 4 col 3</td> </tr> <tr> <td>row 5 col 1</td> <td>row 5 col 2</td> <td>row 5 col 3</td> </tr> <tr> <td>row 6 col 1</td> <td>row 6 col 2</td> <td>row 6 col 3</td> </tr> </table> </div> </body> </html>

对于那些尝试了Maximilian Hils给出的很好的解决方案,但没有成功地让它在Internet Explorer上工作的人,我遇到了同样的问题(Internet Explorer 11),并找到了问题所在。

在Internet Explorer 11中,样式转换(至少使用translate)在<THEAD>上不起作用。我通过将样式应用到循环中的所有<TH>来解决这个问题。这工作。我的JavaScript代码是这样的:

document.getElementById('pnlGridWrap').addEventListener("scroll", function () {
  var translate = "translate(0," + this.scrollTop + "px)";
  var myElements = this.querySelectorAll("th");
  for (var i = 0; i < myElements.length; i++) {
    myElements[i].style.transform=translate;
  }
});

在我的例子中,表格是ASP.NET中的GridView。起初我认为这是因为它没有<THEAD>,但即使我强迫它有一个,它也不工作。然后我发现了我上面写的东西。

这是一个非常好的简单的解决方案。在Chrome浏览器上它是完美的,在Firefox上有点不稳定,在ie浏览器上就更不稳定了。但总的来说,这是个好办法。

博士TL;

如果您的目标是现代浏览器,并且没有奢侈的样式需求:http://jsfiddle.net/dPixie/byB9d/3/…虽然四大版本是相当甜蜜的以及这个版本处理流体宽度好得多。

大家好!

随着HTML5和CSS3的进步,至少对于现代浏览器来说,这是可能的。我提出的稍微有点粗糙的实现可以在这里找到:http://jsfiddle.net/dPixie/byB9d/3/。我已经在FX 25, Chrome 31和IE 10上测试过了…

相关的HTML(在你的文档顶部插入一个HTML5文档类型):

html, body { margin: 0; padding: 0; height: 100%; } section { position: relative; border: 1px solid #000; padding-top: 37px; background: #500; } section.positioned { position: absolute; top: 100px; left: 100px; width: 800px; box-shadow: 0 0 15px #333; } .container { overflow-y: auto; height: 200px; } table { border-spacing: 0; width: 100%; } td+td { border-left: 1px solid #eee; } td, th { border-bottom: 1px solid #eee; background: #ddd; color: #000; padding: 10px 25px; } th { height: 0; line-height: 0; padding-top: 0; padding-bottom: 0; color: transparent; border: none; white-space: nowrap; } th div { position: absolute; background: transparent; color: #fff; padding: 9px 25px; top: 0; margin-left: -25px; line-height: normal; border-left: 1px solid #800; } th:first-child div { border: none; } <section class="positioned"> <div class="container"> <table> <thead> <tr class="header"> <th> Table attribute name <div>Table attribute name</div> </th> <th> Value <div>Value</div> </th> <th> Description <div>Description</div> </th> </tr> </thead> <tbody> <tr> <td>align</td> <td>left, center, right</td> <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td> </tr> <tr> <td>bgcolor</td> <td>rgb(x,x,x), #xxxxxx, colorname</td> <td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td> </tr> <tr> <td>border</td> <td>1,""</td> <td>Specifies whether the table cells should have borders or not</td> </tr> <tr> <td>cellpadding</td> <td>pixels</td> <td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td> </tr> <tr> <td>cellspacing</td> <td>pixels</td> <td>Not supported in HTML5. Specifies the space between cells</td> </tr> <tr> <td>frame</td> <td>void, above, below, hsides, lhs, rhs, vsides, box, border</td> <td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td> </tr> <tr> <td>rules</td> <td>none, groups, rows, cols, all</td> <td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td> </tr> <tr> <td>summary</td> <td>text</td> <td>Not supported in HTML5. Specifies a summary of the content of a table</td> </tr> <tr> <td>width</td> <td>pixels, %</td> <td>Not supported in HTML5. Specifies the width of a table</td> </tr> </tbody> </table> </div> </section>

但是如何? !

简单地说,你有一个表头,你通过使它高0px来隐藏它,它还包含了用作固定表头的div。表的容器在顶部留下了足够的空间来允许绝对定位的标题,并且带有滚动条的表如您所期望的那样出现。

上面的代码使用了定位类来确定表的位置(我在弹出式对话框中使用它),但是您也可以通过从容器中删除定位类来在文档流中使用它。

但是…

它并不完美。Firefox拒绝使标题行为0px(至少我没有找到任何方法),但固执地保持它至少为4px…这不是一个大问题,但取决于你的样式,它会混淆你的边界等。

该表还使用了一种伪列方法,其中容器本身的背景色被用作标题div的背景,这是透明的。

总结

总而言之,根据您的需求,可能会有样式问题,特别是边界或复杂的背景。可计算性可能也有问题,我还没有在各种各样的浏览器中检查它(如果你尝试过,请评论你的经验),但我没有发现任何类似的东西,所以我认为无论如何都值得发布…