是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
这里发布的大多数解决方案都需要jQuery。如果您正在寻找独立于框架的解决方案,请尝试Grid: http://www.matts411.com/post/grid/
它托管在Github上:https://github.com/mmurph211/Grid
它不仅支持固定的页眉,还支持固定的左列和页脚等等。
其他回答
派对来的很晚了,但这仍然是一个派对,以下是我对顺风车的看法:
<div class="h-screen overflow-hidden flex flex-col">
<div class="overflow-y-scroll flex-1">
<table>
<thead class="sticky top-0">
<tr>
<th>Timestamp</th>
<th>Species</th>
</tr>
</thead>
<tbody>
<tr>
<td>2022-02-09T08:20:39.967Z</td>
<td>willow</td>
</tr>
<tr>
<td>2022-02-09T08:21:29.453Z</td>
<td>red osier dogwood</td>
</tr>
<tr>
<td>2022-02-09T08:22:18.984Z</td>
<td>buttonbush</td>
</tr>
</tbody>
</table>
</div>
</div>
以下是一个关于顺风游戏的完整工作示例。
我还创建了一个插件来解决这个问题。我的项目- jQuery。floatThead已经存在了4年多,非常成熟。
它不需要外部样式,也不期望您的表以任何特定的方式进行样式化。支持Internet Explorer9+和Firefox/Chrome浏览器。
目前(2018-05):
在GitHub上有405次提交和998个星级
这里的许多(不是全部)答案都是快速的技巧,可能解决了某个人的问题,但并不适用于每一张桌子。
其他一些插件已经很老了,可能在ie浏览器上运行得很好,但在Firefox和Chrome浏览器上就不行了。
简单的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滚动表
到目前为止,我所见过的所有纯CSS解决方案——尽管它们可能很聪明——都缺乏一定程度的优化,或者在某些情况下不能正常工作。所以,我决定创建我自己的…
特点:
It's pure CSS, so no jQuery required (or any JavaScript code at all, for that matter) You can set the table width to a percent (a.k.a. "fluid") or a fixed value, or let the content determine its width (a.k.a. "auto") Column widths can also be fluid, fixed, or auto. Columns will never become misaligned with headers due to horizontal scrolling (a problem that occurs in every other CSS-based solution I've seen that doesn't require fixed widths). Compatible with all of the popular desktop browsers, including Internet Explorer back to version 8 Clean, polished appearance; no sloppy-looking 1-pixel gaps or misaligned borders; looks the same in all browsers
下面是一些显示流体和自动宽度选项的控件:
流体宽度和高度(适应屏幕大小):jsFiddle(注意,在此配置中,滚动条只在需要时显示,因此您可能必须缩小帧才能看到它) 自动宽度,固定高度(更容易与其他内容集成):jsFiddle
自动宽度,固定高度配置可能有更多的用例,所以我将在下面发布代码。
/* The following 'html' and 'body' rule sets are required only if using a % width or height*/ /*html { width: 100%; height: 100%; }*/ body { box-sizing: border-box; width: 100%; height: 100%; margin: 0; padding: 0 20px 0 20px; text-align: center; } .scrollingtable { box-sizing: border-box; display: inline-block; vertical-align: middle; overflow: hidden; width: auto; /* If you want a fixed width, set it here, else set to auto */ min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */ height: 188px/*100%*/; /* Set table height here; can be fixed value or % */ min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */ font-family: Verdana, Tahoma, sans-serif; font-size: 16px; line-height: 20px; padding: 20px 0 20px 0; /* Need enough padding to make room for caption */ text-align: left; color: black; } .scrollingtable * {box-sizing: border-box;} .scrollingtable > div { position: relative; border-top: 1px solid black; height: 100%; padding-top: 20px; /* This determines column header height */ } .scrollingtable > div:before { top: 0; background: cornflowerblue; /* Header row background color */ } .scrollingtable > div:before, .scrollingtable > div > div:after { content: ""; position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; } .scrollingtable > div > div { min-height: 0/*43px*/; /* If using % height, make this large enough to fit scrollbar arrows */ max-height: 100%; overflow: scroll/*auto*/; /* Set to auto if using fixed or % width; else scroll */ overflow-x: hidden; border: 1px solid black; /* Border around table body */ } .scrollingtable > div > div:after {background: white;} /* Match page background color */ .scrollingtable > div > div > table { width: 100%; border-spacing: 0; margin-top: -20px; /* Inverse of column header height */ /*margin-right: 17px;*/ /* Uncomment if using % width */ } .scrollingtable > div > div > table > caption { position: absolute; top: -20px; /*inverse of caption height*/ margin-top: -1px; /*inverse of border-width*/ width: 100%; font-weight: bold; text-align: center; } .scrollingtable > div > div > table > * > tr > * {padding: 0;} .scrollingtable > div > div > table > thead { vertical-align: bottom; white-space: nowrap; text-align: center; } .scrollingtable > div > div > table > thead > tr > * > div { display: inline-block; padding: 0 6px 0 6px; /*header cell padding*/ } .scrollingtable > div > div > table > thead > tr > :first-child:before { content: ""; position: absolute; top: 0; left: 0; height: 20px; /*match column header height*/ border-left: 1px solid black; /*leftmost header border*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div > div:first-child, .scrollingtable > div > div > table > thead > tr > * + :before { position: absolute; top: 0; white-space: pre-wrap; color: white; /*header row font color*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);} .scrollingtable > div > div > table > thead > tr > * + :before { content: ""; display: block; min-height: 20px; /* Match column header height */ padding-top: 1px; border-left: 1px solid black; /* Borders between header cells */ } .scrollingtable .scrollbarhead {float: right;} .scrollingtable .scrollbarhead:before { position: absolute; width: 100px; top: -1px; /* Inverse border-width */ background: white; /* Match page background color */ } .scrollingtable > div > div > table > tbody > tr:after { content: ""; display: table-cell; position: relative; padding: 0; border-top: 1px solid black; top: -1px; /* Inverse of border width */ } .scrollingtable > div > div > table > tbody {vertical-align: top;} .scrollingtable > div > div > table > tbody > tr {background: white;} .scrollingtable > div > div > table > tbody > tr > * { border-bottom: 1px solid black; padding: 0 6px 0 6px; height: 20px; /* Match column header height */ } .scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;} .scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */ .scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */ <div class="scrollingtable"> <div> <div> <table> <caption>Top Caption</caption> <thead> <tr> <th><div label="Column 1"/></th> <th><div label="Column 2"/></th> <th><div label="Column 3"/></th> <th> <!-- More versatile way of doing column label; requires two identical copies of label --> <div><div>Column 4</div><div>Column 4</div></div> </th> <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW --> </tr> </thead> <tbody> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> </tbody> </table> </div> Faux bottom caption </div> </div> <!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
我用来冻结标题行的方法与d-Pixie的方法类似,因此请参阅他的帖子以获得解释。该技术存在大量错误和限制,只能通过大量额外的CSS和一两个额外的div容器来修复。
这可以在四行代码中清晰地解决。
如果您只关心现代浏览器,那么使用CSS转换可以更容易地实现固定标头。听起来很奇怪,但效果很好:
HTML和CSS保持原样。 没有外部JavaScript依赖。 四行代码。 适用于所有配置(表布局:固定等)。
document.getElementById("wrap").addEventListener("scroll", function(){
var translate = "translate(0,"+this.scrollTop+"px)";
this.querySelector("thead").style.transform = translate;
});
除了Internet Explorer 8-,对CSS转换的支持广泛可用。
下面是完整的例子供参考:
document.getElementById("wrap").addEventListener("scroll",function(){ var translate = "translate(0,"+this.scrollTop+"px)"; this.querySelector("thead").style.transform = translate; }); /* Your existing container */ #wrap { overflow: auto; height: 400px; } /* CSS for demo */ td { background-color: green; width: 200px; height: 100px; } <div id="wrap"> <table> <thead> <tr> <th>Foo</th> <th>Bar</th> </tr> </thead> <tbody> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> <tr><td></td><td></td></tr> </tbody> </table> </div>