是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
这是我们最终使用的解决方案(为了处理一些边缘情况和旧版本的Internet Explorer,我们最终也会在滚动时淡出标题栏,然后在滚动结束时重新淡出,但在Firefox和WebKit浏览器中,这个解决方案是有效的。它假设边界崩溃:崩溃。
此解决方案的关键在于,一旦应用了边界折叠,CSS转换就可以在头部上工作,因此只需拦截滚动事件并正确设置转换即可。你不需要复制任何东西。除非在浏览器中正确地实现这种行为,否则很难想象还有更轻量级的解决方案。
JSFiddle: http://jsfiddle.net/podperson/tH9VU/2/
它被实现为一个简单的jQuery插件。你只需要调用像$('thead').sticky()这样的调用来让你的head's sticky,它们就会一直存在。它适用于一个页面上的多个表和大表中间的头部部分。
$.fn.sticky = function(){
$(this).each( function(){
var thead = $(this),
tbody = thead.next('tbody');
updateHeaderPosition();
function updateHeaderPosition(){
if(
thead.offset().top < $(document).scrollTop()
&& tbody.offset().top + tbody.height() > $(document).scrollTop()
){
var tr = tbody.find('tr').last(),
y = tr.offset().top - thead.height() < $(document).scrollTop()
? tr.offset().top - thead.height() - thead.offset().top
: $(document).scrollTop() - thead.offset().top;
thead.find('th').css({
'z-index': 100,
'transform': 'translateY(' + y + 'px)',
'-webkit-transform': 'translateY(' + y + 'px)'
});
} else {
thead.find('th').css({
'transform': 'none',
'-webkit-transform': 'none'
});
}
}
// See http://www.quirksmode.org/dom/events/scroll.html
$(window).on('scroll', updateHeaderPosition);
});
}
$('thead').sticky();
其他回答
几乎所有的现代浏览器都支持它!
// '.tbl-content' consumed little space for vertical scrollbar, scrollbar width depend on browser/os/platfrom. Here calculate the scollbar width . $(window).on("load resize ", function() { var scrollWidth = $('.tbl-content').width() - $('.tbl-content table').width(); $('.tbl-header').css({ 'padding-right': scrollWidth }); }).resize(); h1 { font-size: 30px; color: #fff; text-transform: uppercase; font-weight: 300; text-align: center; margin-bottom: 15px; } table { width: 100%; table-layout: fixed; } .tbl-header { background-color: rgba(255, 255, 255, 0.3); } .tbl-content { height: 300px; overflow-x: auto; margin-top: 0px; border: 1px solid rgba(255, 255, 255, 0.3); } th { padding: 20px 15px; text-align: left; font-weight: 500; font-size: 12px; color: #fff; text-transform: uppercase; } td { padding: 15px; text-align: left; vertical-align: middle; font-weight: 300; font-size: 12px; color: #fff; border-bottom: solid 1px rgba(255, 255, 255, 0.1); } /* demo styles */ @import url(https://fonts.googleapis.com/css?family=Roboto:400,500,300,700); body { background: -webkit-linear-gradient(left, #25c481, #25b7c4); background: linear-gradient(to right, #25c481, #25b7c4); font-family: 'Roboto', sans-serif; } section { margin: 50px; } /* follow me template */ .made-with-love { margin-top: 40px; padding: 10px; clear: left; text-align: center; font-size: 10px; font-family: arial; color: #fff; } .made-with-love i { font-style: normal; color: #F50057; font-size: 14px; position: relative; top: 2px; } .made-with-love a { color: #fff; text-decoration: none; } .made-with-love a:hover { text-decoration: underline; } /* for custom scrollbar for webkit browser*/ ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); } ::-webkit-scrollbar-thumb { -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); } <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <section> <!--for demo wrap--> <h1>Fixed Table header</h1> <div class="tbl-header"> <table cellpadding="0" cellspacing="0" border="0"> <thead> <tr> <th>Code</th> <th>Company</th> <th>Price</th> <th>Change</th> <th>Change %</th> </tr> </thead> </table> </div> <div class="tbl-content"> <table cellpadding="0" cellspacing="0" border="0"> <tbody> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> <tr> <td>AAC</td> <td>AUSTRALIAN COMPANY </td> <td>$1.38</td> <td>+2.01</td> <td>-0.36%</td> </tr> <tr> <td>AAD</td> <td>AUSENCO</td> <td>$2.38</td> <td>-0.01</td> <td>-1.36%</td> </tr> <tr> <td>AAX</td> <td>ADELAIDE</td> <td>$3.22</td> <td>+0.01</td> <td>+1.36%</td> </tr> <tr> <td>XXD</td> <td>ADITYA BIRLA</td> <td>$1.02</td> <td>-1.01</td> <td>+2.36%</td> </tr> </tbody> </table> </div> </section>
支持固定页脚
我扩展了内森的功能,也支持一个固定的页脚和最大高度。 此外,该函数将设置CSS本身,您只需要支持宽度。
用法:
固定高度:
$('table').scrollableTable({ height: 100 });
最大高度(如果浏览器支持CSS 'max-height'选项):
$('table').scrollableTable({ maxHeight: 100 });
脚本:
jQuery.fn.scrollableTable = function(options) {
var $originalTable, $headTable, $bodyTable, $footTable, $scrollableDiv, originalWidths;
// Prepare the separate parts of the table
$originalTable = $(this);
$headTable = $originalTable.clone();
$headTable.find('tbody').remove();
$headTable.find('tfoot').remove();
$bodyTable = $originalTable.clone();
$bodyTable.find('thead').remove();
$bodyTable.find('tfoot').remove();
$footTable = $originalTable.clone();
$footTable.find('thead').remove();
$footTable.find('tbody').remove();
// Grab the original column widths and set them in the separate tables
originalWidths = $originalTable.find('tr:first td').map(function() {
return $(this).width();
});
$.each([$headTable, $bodyTable, $footTable], function(index, $table) {
$table.find('tr:first td').each(function(i) {
$(this).width(originalWidths[i]);
});
});
// The div that makes the body table scroll
$scrollableDiv = $('<div/>').css({
'overflow-y': 'scroll'
});
if(options.height) {
$scrollableDiv.css({'height': options.height});
}
else if(options.maxHeight) {
$scrollableDiv.css({'max-height': options.maxHeight});
}
// Add the new separate tables and remove the original one
$headTable.insertAfter($originalTable);
$bodyTable.insertAfter($headTable);
$footTable.insertAfter($bodyTable);
$bodyTable.wrap($scrollableDiv);
$originalTable.remove();
};
对于那些尝试了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浏览器上就更不稳定了。但总的来说,这是个好办法。
这是我们最终使用的解决方案(为了处理一些边缘情况和旧版本的Internet Explorer,我们最终也会在滚动时淡出标题栏,然后在滚动结束时重新淡出,但在Firefox和WebKit浏览器中,这个解决方案是有效的。它假设边界崩溃:崩溃。
此解决方案的关键在于,一旦应用了边界折叠,CSS转换就可以在头部上工作,因此只需拦截滚动事件并正确设置转换即可。你不需要复制任何东西。除非在浏览器中正确地实现这种行为,否则很难想象还有更轻量级的解决方案。
JSFiddle: http://jsfiddle.net/podperson/tH9VU/2/
它被实现为一个简单的jQuery插件。你只需要调用像$('thead').sticky()这样的调用来让你的head's sticky,它们就会一直存在。它适用于一个页面上的多个表和大表中间的头部部分。
$.fn.sticky = function(){
$(this).each( function(){
var thead = $(this),
tbody = thead.next('tbody');
updateHeaderPosition();
function updateHeaderPosition(){
if(
thead.offset().top < $(document).scrollTop()
&& tbody.offset().top + tbody.height() > $(document).scrollTop()
){
var tr = tbody.find('tr').last(),
y = tr.offset().top - thead.height() < $(document).scrollTop()
? tr.offset().top - thead.height() - thead.offset().top
: $(document).scrollTop() - thead.offset().top;
thead.find('th').css({
'z-index': 100,
'transform': 'translateY(' + y + 'px)',
'-webkit-transform': 'translateY(' + y + 'px)'
});
} else {
thead.find('th').css({
'transform': 'none',
'-webkit-transform': 'none'
});
}
}
// See http://www.quirksmode.org/dom/events/scroll.html
$(window).on('scroll', updateHeaderPosition);
});
}
$('thead').sticky();
我发现这个解决方案-移动标题行在表上面的表与数据:
<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>