是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
很多人似乎都在寻找这个答案。我发现它隐藏在这里的另一个问题的答案:同步两个不同帧的表之间的列宽度,等等
在我尝试过的几十种方法中,这是我发现的唯一一种可靠的方法,可以让你有一个滚动的底部表,头部表具有相同的宽度。
以下是我是如何做到的,首先我改进了上面的jsfiddle来创建这个函数,它在td和th上都可以工作(以防绊倒其他人谁使用th来样式化他们的标题行)。
var setHeaderTableWidth= function (headertableid,basetableid) {
$("#"+headertableid).width($("#"+basetableid).width());
$("#"+headertableid+" tr th").each(function (i) {
$(this).width($($("#"+basetableid+" tr:first td")[i]).width());
});
$("#" + headertableid + " tr td").each(function (i) {
$(this).width($($("#" + basetableid + " tr:first td")[i]).width());
});
}
接下来,你需要创建两个表,注意头表应该有一个额外的TD,以便在顶部表中为滚动条留出空间,就像这样:
<table id="headertable1" class="input-cells table-striped">
<thead>
<tr style="background-color:darkgray;color:white;"><th>header1</th><th>header2</th><th>header3</th><th>header4</th><th>header5</th><th>header6</th><th></th></tr>
</thead>
</table>
<div id="resizeToBottom" style="overflow-y:scroll;overflow-x:hidden;">
<table id="basetable1" class="input-cells table-striped">
<tbody >
<tr>
<td>testdata</td>
<td>2</td>
<td>3</td>
<td>4</span></td>
<td>55555555555555</td>
<td>test</td></tr>
</tbody>
</table>
</div>
然后这样做:
setHeaderTableWidth('headertable1', 'basetable1');
$(window).resize(function () {
setHeaderTableWidth('headertable1', 'basetable1');
});
这是我在Stack Overflow上找到的唯一解决方案,可以解决许多类似的问题,在我所有的情况下都有效。
例如,我尝试了不与durandal工作的jQuery stickytables插件和谷歌代码项目https://code.google.com/p/js-scroll-table-header/issues/detail?id=2
其他涉及克隆表的解决方案性能很差,或者很糟糕,并不是在所有情况下都有效。
没有必要使用这些过于复杂的解决方案。只需像下面的例子一样创建两个表,并像这里描述的那样调用setHeaderTableWidth函数,然后嘣,你就完成了。
如果这对你不起作用,你可能在玩你的CSS box-sizing属性,你需要正确设置它。很容易意外地搞砸你的CSS内容。有很多事情都可能出错,所以要注意/小心。这种方法对我很有效。
其他回答
我发现这个解决方案-移动标题行在表上面的表与数据:
<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>
补充@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
我意识到这个问题允许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/
两个div,一个用于头,一个用于数据。使数据div可滚动,并使用JavaScript将标题中的列的宽度设置为与数据中的宽度相同。我认为数据列的宽度应该是固定的,而不是动态的。
这可以在四行代码中清晰地解决。
如果您只关心现代浏览器,那么使用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>