是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
我一直在寻找一个解决方案,发现大多数答案都不工作或不适合我的情况,所以我用jQuery编写了一个简单的解决方案。
这是解决方案大纲:
克隆需要固定表头的表,并放置 在原拷贝之上的克隆拷贝。 从主表上拆下表体。 从底部表中删除表头。 调整列的宽度。(我们跟踪原始列的宽度)
下面是一个可运行的演示代码。
function scrolify(tblAsJQueryObject, height) { var oTbl = tblAsJQueryObject; // for very large tables you can remove the four lines below // and wrap the table with <div> in the mark-up and assign // height and overflow property var oTblDiv = $("<div/>"); oTblDiv.css('height', height); oTblDiv.css('overflow', 'scroll'); oTbl.wrap(oTblDiv); // save original width oTbl.attr("data-item-original-width", oTbl.width()); oTbl.find('thead tr td').each(function() { $(this).attr("data-item-original-width", $(this).width()); }); oTbl.find('tbody tr:eq(0) td').each(function() { $(this).attr("data-item-original-width", $(this).width()); }); // clone the original table var newTbl = oTbl.clone(); // remove table header from original table oTbl.find('thead tr').remove(); // remove table body from new table newTbl.find('tbody tr').remove(); oTbl.parent().parent().prepend(newTbl); newTbl.wrap("<div/>"); // replace ORIGINAL COLUMN width newTbl.width(newTbl.attr('data-item-original-width')); newTbl.find('thead tr td').each(function() { $(this).width($(this).attr("data-item-original-width")); }); oTbl.width(oTbl.attr('data-item-original-width')); oTbl.find('tbody tr:eq(0) td').each(function() { $(this).width($(this).attr("data-item-original-width")); }); } $(document).ready(function() { scrolify($('#tblNeedsScrolling'), 160); // 160 is height }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> <div style="width:300px;border:6px green solid;"> <table border="1" width="100%" id="tblNeedsScrolling"> <thead> <tr><th>Header 1</th><th>Header 2</th></tr> </thead> <tbody> <tr><td>row 1, cell 1</td><td>row 1, cell 2</td></tr> <tr><td>row 2, cell 1</td><td>row 2, cell 2</td></tr> <tr><td>row 3, cell 1</td><td>row 3, cell 2</td></tr> <tr><td>row 4, cell 1</td><td>row 4, cell 2</td></tr> <tr><td>row 5, cell 1</td><td>row 5, cell 2</td></tr> <tr><td>row 6, cell 1</td><td>row 6, cell 2</td></tr> <tr><td>row 7, cell 1</td><td>row 7, cell 2</td></tr> <tr><td>row 8, cell 1</td><td>row 8, cell 2</td></tr> </tbody> </table> </div>
该解决方案支持Chrome和IE浏览器。因为它是基于jQuery的,所以在其他jQuery支持的浏览器中也能正常工作。
其他回答
补充@Daniel Waltrip的回答。表需附以div位置:相对,以便与工作位置:粘。所以我想在这里发布我的示例代码。
CSS
/* Set table width/height as you want.*/
div.freeze-header {
position: relative;
max-height: 150px;
max-width: 400px;
overflow:auto;
}
/* Use position:sticky to freeze header on top*/
div.freeze-header > table > thead > tr > th {
position: sticky;
top: 0;
background-color:yellow;
}
/* below is just table style decoration.*/
div.freeze-header > table {
border-collapse: collapse;
}
div.freeze-header > table td {
border: 1px solid black;
}
HTML
<html>
<body>
<div>
other contents ...
</div>
<div>
other contents ...
</div>
<div>
other contents ...
</div>
<div class="freeze-header">
<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>
<th> header 8 </th>
<th> header 9 </th>
<th> header 10 </th>
<th> header 11 </th>
<th> header 12 </th>
<th> header 13 </th>
<th> header 14 </th>
<th> header 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </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>
<td> data 8 </td>
<td> data 9 </td>
<td> data 10 </td>
<td> data 11 </td>
<td> data 12 </td>
<td> data 13 </td>
<td> data 14 </td>
<td> data 15 </td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Demo
我希望我能早点找到@Mark的解决方案,但在我看到这个SO问题之前,我自己写了一个……
我的是一个非常轻量级的jQuery插件,它支持固定的页眉、页脚、列跨越(colspan)、调整大小、水平滚动,以及滚动开始前可选的显示行数。
jQuery。scrollTableBody (GitHub)
只要你有一个合适的<thead>, <tbody>,和(可选)<tfoot>的表,你所需要做的就是:
$('table').scrollTableBody();
我刚刚完成了一个jQuery插件,将采取有效的单一表使用有效的HTML(必须有一个标题和tbody),并将输出一个表,有固定的标题,可选的固定页脚,可以是一个克隆的标题或任何你选择的内容(分页等)。如果你想利用更大的显示器,它也会在浏览器调整大小时调整表的大小。另一个添加的特性是,如果表列不能全部放入视图,则可以侧滚动。
http://fixedheadertable.com/
在github: http://markmalek.github.com/Fixed-Header-Table/
它非常容易安装,你可以为它创建自己的自定义样式。它还在所有浏览器中使用圆角。请记住,我刚刚发布了它,所以它在技术上仍然是测试版,有一些小问题我正在解决。
它适用于Internet Explorer 7、Internet Explorer 8、Safari、Firefox和Chrome浏览器。
所有从CSS规范之外解决这个问题的尝试都是我们真正想要的:按照THEAD的隐含承诺交付。
这个冻结表头的问题长期以来一直是HTML/CSS中的一个开放性问题。
在理想的情况下,应该有一个纯css解决方案来解决这个问题。不幸的是,似乎没有一个合适的。
相关标准-关于此主题的讨论包括:
粘性定位提案网址:http://lists.w3.org/Archives/Public/www-style/2012Jun/0627.html 请在阿特金斯提出的“位置-根”、“位置-包含”或“位置-限制”的建议中打上标签:http://www.xanthir.com/blog/b48H0
更新:Firefox的发货位置:粘在版本32。每个人都会赢!
这不是固定标题行的精确解决方案,但我创建了一种相当巧妙的方法,在整个长表中重复标题行,但仍然保持排序能力。
这个简洁的小选项需要jQuery tablesorter插件。下面是它的工作原理:
HTML
<table class="tablesorter boxlist" id="pmtable">
<thead class="fixedheader">
<tr class="boxheadrow">
<th width="70px" class="header">Job Number</th>
<th width="10px" class="header">Pri</th>
<th width="70px" class="header">CLLI</th>
<th width="35px" class="header">Market</th>
<th width="35px" class="header">Job Status</th>
<th width="65px" class="header">Technology</th>
<th width="95px;" class="header headerSortDown">MEI</th>
<th width="95px" class="header">TEO Writer</th>
<th width="75px" class="header">Quote Due</th>
<th width="100px" class="header">Engineer</th>
<th width="75px" class="header">ML Due</th>
<th width="75px" class="header">ML Complete</th>
<th width="75px" class="header">SPEC Due</th>
<th width="75px" class="header">SPEC Complete</th>
<th width="100px" class="header">Install Supervisor</th>
<th width="75px" class="header">MasTec OJD</th>
<th width="75px" class="header">Install Start</th>
<th width="30px" class="header">Install Hours</th>
<th width="75px" class="header">Revised CRCD</th>
<th width="75px" class="header">Latest Ship-To-Site</th>
<th width="30px" class="header">Total Parts</th>
<th width="30px" class="header">OEM Rcvd</th>
<th width="30px" class="header">Minor Rcvd</th>
<th width="30px" class="header">Total Received</th>
<th width="30px" class="header">% On Site</th>
<th width="60px" class="header">Actions</th>
</tr>
</thead>
<tbody class="scrollable">
<tr data-job_id="3548" data-ml_id="" class="odd">
<td class="c black">FL-8-RG9UP</td>
<td data-pri="2" class="priority c yellow">M</td>
<td class="c">FTLDFLOV</td>
<td class="c">SFL</td>
<td class="c">NOI</td>
<td class="c">TRANSPORT</td>
<td class="c"></td>
<td class="c">Chris Byrd</td>
<td class="c">Apr 13, 2013</td>
<td class="c">Kris Hall</td>
<td class="c">May 20, 2013</td>
<td class="c">May 20, 2013</td>
<td class="c">Jun 5, 2013</td>
<td class="c">Jun 7, 2013</td>
<td class="c">Joseph Fitz</td>
<td class="c">Jun 10, 2013</td>
<td class="c">TBD</td>
<td class="c">123</td>
<td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Jul 26, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058616"></td>
<td class="c">TBD</td>
<td class="c">N/A</td>
<td class="c">N/A</td>
<td class="c">N/A</td>
<td class="c">N/A</td>
<td class="c">N/A</td>
<td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span></td>
</tr>
<tr data-job_id="4264" data-ml_id="2959" class="even">
<td class="c black">MTS13009SF</td>
<td data-pri="2" class="priority c yellow">M</td>
<td class="c">OJUSFLTL</td>
<td class="c">SFL</td>
<td class="c">NOI</td>
<td class="c">TRANSPORT</td>
<td class="c"></td>
<td class="c">DeMarcus Stewart</td>
<td class="c">May 22, 2013</td>
<td class="c">Ryan Alsobrook</td>
<td class="c">Jun 19, 2013</td>
<td class="c">Jun 27, 2013</td>
<td class="c">Jun 19, 2013</td>
<td class="c">Jul 4, 2013</td>
<td class="c">Randy Williams</td>
<td class="c">Jun 21, 2013</td>
<td class="c">TBD</td>
<td class="c">95</td>
<td class="c revised_crcd"><input readonly="true" name="revised_crcd" value="Aug 9, 2013" type="text" size="12" class="smInput r_crcd c hasDatepicker" id="dp1377194058632"></td><td class="c">TBD</td>
<td class="c">0</td>
<td class="c">0.00%</td>
<td class="c">0.00%</td>
<td class="c">0.00%</td>
<td class="c">0.00%</td>
<td class="actions"><span style="float:left;" class="ui-icon ui-icon-folder-open editJob" title="View this job" s="" details'=""></span><input style="float:left;" type="hidden" name="req_ship" class="reqShip hasDatepicker" id="dp1377194058464"><span style="float:left;" class="ui-icon ui-icon-calendar requestShip" title="Schedule this job for shipping"></span><span class="ui-icon ui-icon-info viewOrderInfo" style="float:left;" title="Show material details for this order"></span></td>
</tr>
.
.
.
.
<tr class="boxheadrow repeated-header">
<th width="70px" class="header">Job Number</th>
<th width="10px" class="header">Pri</th>
<th width="70px" class="header">CLLI</th>
<th width="35px" class="header">Market</th>
<th width="35px" class="header">Job Status</th>
<th width="65px" class="header">Technology</th>
<th width="95px;" class="header">MEI</th>
<th width="95px" class="header">TEO Writer</th>
<th width="75px" class="header">Quote Due</th>
<th width="100px" class="header">Engineer</th>
<th width="75px" class="header">ML Due</th>
<th width="75px" class="header">ML Complete</th>
<th width="75px" class="header">SPEC Due</th>
<th width="75px" class="header">SPEC Complete</th>
<th width="100px" class="header">Install Supervisor</th>
<th width="75px" class="header">MasTec OJD</th>
<th width="75px" class="header">Install Start</th>
<th width="30px" class="header">Install Hours</th>
<th width="75px" class="header">Revised CRCD</th>
<th width="75px" class="header">Latest Ship-To-Site</th>
<th width="30px" class="header">Total Parts</th>
<th width="30px" class="header">OEM Rcvd</th>
<th width="30px" class="header">Minor Rcvd</th>
<th width="30px" class="header">Total Received</th>
<th width="30px" class="header">% On Site</th>
<th width="60px" class="header">Actions</th>
</tr>
显然,我的表的行要比这个多很多。确切地说是193,但是你可以看到标题行重复的地方。重复的标题行是由这个函数建立的:
jQuery
// Clone the original header row and add the "repeated-header" class
var tblHeader = $('tr.boxheadrow').clone().addClass('repeated-header');
// Add the cloned header with the new class every 34th row (or as you see fit)
$('tbody tr:odd:nth-of-type(17n)').after(tblHeader);
// On the 'sortStart' routine, remove all the inserted header rows
$('#pmtable').bind('sortStart', function() {
$('.repeated-header').remove();
// On the 'sortEnd' routine, add back all the header row lines.
}).bind('sortEnd', function() {
$('tbody tr:odd:nth-of-type(17n)').after(tblHeader);
});