是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
几乎所有的现代浏览器都支持它!
// '.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>
其他回答
对于那些尝试了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浏览器上就更不稳定了。但总的来说,这是个好办法。
我意识到这个问题允许JavaScript,但这里有一个纯CSS解决方案,我还允许表水平展开。它在ie10和最新的Chrome和Firefox浏览器上进行了测试。jsFiddle的链接在底部。
HTML:
Putting some text here to differentiate between the header
aligning with the top of the screen and the header aligning
with the top of one of its ancestor containers.
<div id="positioning-container">
<div id="scroll-container">
<table>
<colgroup>
<col class="col1"></col>
<col class="col2"></col>
</colgroup>
<thead>
<th class="header-col1"><div>Header 1</div></th>
<th class="header-col2"><div>Header 2</div></th>
</thead>
<tbody>
<tr><td>Cell 1.1</td><td>Cell 1.2</td></tr>
<tr><td>Cell 2.1</td><td>Cell 2.2</td></tr>
<tr><td>Cell 3.1</td><td>Cell 3.2</td></tr>
<tr><td>Cell 4.1</td><td>Cell 4.2</td></tr>
<tr><td>Cell 5.1</td><td>Cell 5.2</td></tr>
<tr><td>Cell 6.1</td><td>Cell 6.2</td></tr>
<tr><td>Cell 7.1</td><td>Cell 7.2</td></tr>
</tbody>
</table>
</div>
</div>
而CSS:
table{
border-collapse: collapse;
table-layout: fixed;
width: 100%;
}
/* Not required, just helps with alignment for this example */
td, th{
padding: 0;
margin: 0;
}
tbody{
background-color: #ddf;
}
thead {
/* Keeps the header in place. Don't forget top: 0 */
position: absolute;
top: 0;
background-color: #ddd;
/* The 17px is to adjust for the scrollbar width.
* This is a new css value that makes this pure
* css example possible */
width: calc(100% - 17px);
height: 20px;
}
/* Positioning container. Required to position the
* header since the header uses position:absolute
* (otherwise it would position at the top of the screen) */
#positioning-container{
position: relative;
}
/* A container to set the scroll-bar and
* includes padding to move the table contents
* down below the header (padding = header height) */
#scroll-container{
overflow-y: auto;
padding-top: 20px;
height: 100px;
}
.header-col1{
background-color: red;
}
/* Fixed-width header columns need a div to set their width */
.header-col1 div{
width: 100px;
}
/* Expandable columns need a width set on the th tag */
.header-col2{
width: 100%;
}
.col1 {
width: 100px;
}
.col2{
width: 100%;
}
http://jsfiddle.net/HNHRv/3/
所有从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插件
这是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);
};
我还创建了一个插件来解决这个问题。我的项目- jQuery。floatThead已经存在了4年多,非常成熟。
它不需要外部样式,也不期望您的表以任何特定的方式进行样式化。支持Internet Explorer9+和Firefox/Chrome浏览器。
目前(2018-05):
在GitHub上有405次提交和998个星级
这里的许多(不是全部)答案都是快速的技巧,可能解决了某个人的问题,但并不适用于每一张桌子。
其他一些插件已经很老了,可能在ie浏览器上运行得很好,但在Firefox和Chrome浏览器上就不行了。