是否有跨浏览器的CSS / JavaScript技术来显示较长的HTML表,以使列标题在屏幕上保持固定并且不随表主体滚动。考虑一下Microsoft Excel中的“冻结窗格”效果。
我希望能够滚动浏览表的内容,但始终能够看到顶部的列标题。
thead th { position: sticky; top: 0; }
。Safari需要供应商前缀:-webkit-sticky
是否有跨浏览器的CSS / JavaScript技术来显示较长的HTML表,以使列标题在屏幕上保持固定并且不随表主体滚动。考虑一下Microsoft Excel中的“冻结窗格”效果。
我希望能够滚动浏览表的内容,但始终能够看到顶部的列标题。
thead th { position: sticky; top: 0; }
。Safari需要供应商前缀:-webkit-sticky
Answers:
一段时间以来,我一直在寻找解决方案,但发现大多数答案不起作用或不适合我的情况,因此我用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支持的浏览器中也可以使用。
如果您只关心现代浏览器,则可以使用CSS转换轻松实现固定标头。听起来很奇怪,但效果很好:
document.getElementById("wrap").addEventListener("scroll", function(){
var translate = "translate(0,"+this.scrollTop+"px)";
this.querySelector("thead").style.transform = translate;
});
除Internet Explorer 8外,对CSS转换的支持广泛可用。
这是完整的示例供参考:
$(this).addClass('border')
更改表的其余部分时,我在border类中传递的字体,大小,颜色也是如此。但是,不向固定标题添加行。赞赏,关于如何解决此问题的任何输入
我刚刚完成了一个jQuery插件的组装,该插件将使用有效的HTML来获取有效的单个表(必须具有thead和tbody),并将输出具有固定页眉,可选固定页脚的表,该页脚可以是克隆的页眉,也可以是任何您选择的内容(分页等)。如果要利用较大的监视器,则在调整浏览器大小时,它还将调整表的大小。如果表的列不能全部显示在视图中,则另一个附加功能是可以侧面滚动。
在github上:http : //markmalek.github.com/Fixed-Header-Table/
设置非常容易,您可以为其创建自己的自定义样式。它还在所有浏览器中使用圆角。请记住,我刚刚发布了它,因此从技术上来说它仍然是beta版,我要解决的问题很少。
它适用于Internet Explorer 7,Internet Explorer 8,Safari,Firefox和Chrome。
我还创建了一个可解决此问题的插件。我的项目jQuery.floatThead已经存在了4年多了,并且非常成熟。
它不需要外部样式,也不希望您的表以任何特定方式设置样式。它支持Internet Explorer9 +和Firefox / Chrome。
目前(2018-05)它具有:
GitHub上的405次提交和998星
这里的许多(不是全部)答案都是快速的技巧,它们可能已经解决了一个人遇到的问题,但是并不能在每个桌子上都起作用。
其他一些插件较旧,可能与Internet Explorer兼容,但在Firefox和Chrome上将无法使用。
如果您以现代浏览器为目标,并且没有过分的样式需求:http : //jsfiddle.net/dPixie/byB9d/3/ ...虽然有四个大版本也很不错,但该版本在处理宽度方面要好得多。
随着HTML5和CSS3的发展,至少在现代浏览器中,这已经成为可能。我想出的有点黑的实现可以在这里找到:http : //jsfiddle.net/dPixie/byB9d/3/。我已经在FX 25,Chrome 31和IE 10中对其进行了测试...
相关HTML(不过,在文档顶部插入HTML5文档类型):
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
section {
position: relative;
border: 1px solid #000;
padding-top: 37px;
background: #500;
}
section.positioned {
position: absolute;
top: 100px;
left: 100px;
width: 800px;
box-shadow: 0 0 15px #333;
}
.container {
overflow-y: auto;
height: 200px;
}
table {
border-spacing: 0;
width: 100%;
}
td+td {
border-left: 1px solid #eee;
}
td,
th {
border-bottom: 1px solid #eee;
background: #ddd;
color: #000;
padding: 10px 25px;
}
th {
height: 0;
line-height: 0;
padding-top: 0;
padding-bottom: 0;
color: transparent;
border: none;
white-space: nowrap;
}
th div {
position: absolute;
background: transparent;
color: #fff;
padding: 9px 25px;
top: 0;
margin-left: -25px;
line-height: normal;
border-left: 1px solid #800;
}
th:first-child div {
border: none;
}
<section class="positioned">
<div class="container">
<table>
<thead>
<tr class="header">
<th>
Table attribute name
<div>Table attribute name</div>
</th>
<th>
Value
<div>Value</div>
</th>
<th>
Description
<div>Description</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>align</td>
<td>left, center, right</td>
<td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the alignment of a table according to surrounding text</td>
</tr>
<tr>
<td>bgcolor</td>
<td>rgb(x,x,x), #xxxxxx, colorname</td>
<td>Not supported in HTML5. Deprecated in HTML 4.01. Specifies the background color for a table</td>
</tr>
<tr>
<td>border</td>
<td>1,""</td>
<td>Specifies whether the table cells should have borders or not</td>
</tr>
<tr>
<td>cellpadding</td>
<td>pixels</td>
<td>Not supported in HTML5. Specifies the space between the cell wall and the cell content</td>
</tr>
<tr>
<td>cellspacing</td>
<td>pixels</td>
<td>Not supported in HTML5. Specifies the space between cells</td>
</tr>
<tr>
<td>frame</td>
<td>void, above, below, hsides, lhs, rhs, vsides, box, border</td>
<td>Not supported in HTML5. Specifies which parts of the outside borders that should be visible</td>
</tr>
<tr>
<td>rules</td>
<td>none, groups, rows, cols, all</td>
<td>Not supported in HTML5. Specifies which parts of the inside borders that should be visible</td>
</tr>
<tr>
<td>summary</td>
<td>text</td>
<td>Not supported in HTML5. Specifies a summary of the content of a table</td>
</tr>
<tr>
<td>width</td>
<td>pixels, %</td>
<td>Not supported in HTML5. Specifies the width of a table</td>
</tr>
</tbody>
</table>
</div>
</section>
简单地说,您有一个表头,您可以通过将表头设置为0px高来隐藏它,其中还包含用作固定头的div。表格的容器在顶部留有足够的空间以容纳绝对定位的标题,并且带有滚动条的表格如您所愿。
上面的代码使用定位类绝对定位表(我在弹出式对话框中使用它),但是您也可以通过删除 positioned
从容器中该类。
这不是完美的。Firefox拒绝将标题行设置为0px(至少我没有找到任何方法),但顽固地将其保持在至少4px……这不是一个大问题,但是取决于您的样式,它会与边框混在一起等等。
该表还使用了仿列方法,其中容器本身的背景色用作透明的标题div的背景。
总而言之,取决于您的要求,尤其是边框或复杂的背景,可能会出现样式问题。可计算性也可能存在问题,我尚未在各种各样的浏览器中进行过检查(如果您尝试过,请在您的经验中发表评论),但是我没有找到类似的东西,因此我认为值得发布反正...
<section>
元素)仅需高度限制即可使其溢出并显示滚动。任何会使容器溢出的布局都可以使用。如果您发现没有这种情况,请发布小提琴的链接。
padding-top
值还意味着,如果表标题文本在多行上,它将显示在表单元格的顶部。可惜,因为在大多数情况下,这就像一种魅力。真的很好招用div
在th
绕过列大小问题大多数其他解决方案都有。
从CSS规范之外解决此问题的所有尝试都是我们真正想要的东西的苍白阴影:交付THEAD的隐含承诺。
很长一段时间以来,这个表格冻结标题问题一直是HTML / CSS的一个开放式伤口。
在一个完美的世界中,将有一个纯CSS解决此问题的方法。不幸的是,似乎没有一个合适的解决方案。
有关此主题的相关标准的讨论包括:
更新:Firefox position:sticky
版本为32。每个人都赢了!
thead th { position: sticky; top: 0; }
。我们可以更新此答案以清楚地说明这一点吗?
这是固定表头的jQuery插件。它允许整个页面滚动,并在到达顶部时冻结标题。它与Twitter Bootstrap表很好地配合。
GitHub存储库:https : //github.com/oma/table-fixed-header
它不只滚动表内容。寻找其他工具,作为其他答案之一。您可以决定最适合您的情况。
这里发布的大多数解决方案都需要jQuery。如果您正在寻找独立于框架的解决方案,请尝试使用Grid:http : //www.matts411.com/post/grid/
它托管在Github上:https : //github.com/mmurph211/Grid
它不仅支持固定的页眉,还支持固定的左列和页脚。
CSS属性position: sticky
在大多数现代浏览器中都有很好的支持(Edge出现了问题,请参见下文)。
这使我们可以很轻松地解决固定标头的问题:
thead th { position: sticky; top: 0; }
Safari需要供应商前缀:-webkit-sticky
。
对于Firefox,我必须将min-height: 0
父元素添加到一个。我完全忘记了为什么需要这样做。
最不幸的是,Microsoft Edge实施似乎只是半成品。至少在测试中,我有一些闪烁且未对齐的表格单元。该桌子仍然可用,但存在重大美学问题。
position: sticky;
与具有一个div里面的表overflow: scroll;
,overflow-x: scroll;
或overflow-y: scroll;
。在现代浏览器中,这似乎是固定表标题和列的最佳和最简单的解决方案。这个答案需要投票给最高。
到目前为止,我见过的所有纯CSS解决方案(尽管它们可能很聪明)都缺乏一定程度的改进,或者只是在某些情况下无法正常工作。因此,我决定创建自己的...
特征:
以下是一些小提琴,它们显示了流畅和自动宽度选项:
“自动宽度,固定高度”配置可能有更多用例,因此我将在下面发布代码。
/* 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容器来解决。
这是Mahes解决方案的一种变体。你可以这样称呼它$('table#foo').scrollableTable();
这个想法是:
thead
和分割tbody
成单独的table
元素table
的div.scrollable
div.scrollable
实际滚动CSS可能是:
div.scrollable { height: 300px; overflow-y: scroll;}
就是说,它适用于我的目的,您可以随意使用和修改它。
这是插件:
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);
};
:)
不太干净,但是纯HTML / CSS解决方案。
table {
overflow-x:scroll;
}
tbody {
max-height: /*your desired max height*/
overflow-y:scroll;
display:block;
}
针对IE8 + JSFiddle示例进行了更新
我扩展了Nathan的功能,以支持固定的页脚和最大高度。另外,该函数将设置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();
};
不知何故,我最终Position:Sticky
在案子上做得很好:
table{
width: 100%;
border: collapse;
}
th{
position: sticky;
top: 0px;
border: 1px solid black;
background: #ff5722;
color: #f5f5f5;
font-weight: 600;
}
td{
background: #d3d3d3;
border: 1px solid black;
color: #f5f5f5;
font-weight: 600;
}
div{
height: 150px
overflow: auto;
width: 100%
}
<div>
<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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</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>
</tr>
</tbody>
</table>
</div>
两个div,一个用于标头,一个用于数据。使数据div可滚动,并使用JavaScript设置标题中列的宽度与数据中的宽度相同。我认为数据列的宽度需要固定而不是动态。
我意识到这个问题允许使用JavaScript,但这是我处理过的纯CSS解决方案,它还允许表格水平扩展。它已通过Internet Explorer 10以及最新的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%;
}
对于那些尝试了Maximilian Hils给出的不错的解决方案但没有成功使其与Internet Explorer一起使用的人来说,我遇到了同样的问题(Internet Explorer 11),并找出了问题所在。
在Internet Explorer 11中,样式转换(至少在转换时)不起作用<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上有点生涩,在Internet Explorer上则更加生涩。但总而言之,这是一个很好的解决方案。
我希望能早点找到@Mark的解决方案,但是在看到这个问题之前,我去写了自己的解决方案...
我的是一个非常轻巧的jQuery插件,它支持固定的页眉,页脚,列跨度(colspan),调整大小,水平滚动以及滚动开始之前要显示的可选行数。
jQuery.scrollTableBody(GitHub)
只要你有一台合适的<thead>
,<tbody>
和(可选)<tfoot>
,所有你需要做的是这样的:
$('table').scrollTableBody();
我找到了这种解决方法-将表头行移到数据上方的表中:
<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>
通过将StickyTableHeaders jQuery插件应用于表,当您向下滚动时,列标题将停留在视口的顶部。
例:
$(function () {
$("table").stickyTableHeaders();
});
/*! Copyright (c) 2011 by Jonas Mosbech - https://github.com/jmosbech/StickyTableHeaders
MIT license info: https://github.com/jmosbech/StickyTableHeaders/blob/master/license.txt */
;
(function ($, window, undefined) {
'use strict';
var name = 'stickyTableHeaders',
id = 0,
defaults = {
fixedOffset: 0,
leftOffset: 0,
marginTop: 0,
scrollableArea: window
};
function Plugin(el, options) {
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this;
// Access to jQuery and DOM versions of element
base.$el = $(el);
base.el = el;
base.id = id++;
base.$window = $(window);
base.$document = $(document);
// Listen for destroyed, call teardown
base.$el.bind('destroyed',
$.proxy(base.teardown, base));
// Cache DOM refs for performance reasons
base.$clonedHeader = null;
base.$originalHeader = null;
// Keep track of state
base.isSticky = false;
base.hasBeenSticky = false;
base.leftOffset = null;
base.topOffset = null;
base.init = function () {
base.$el.each(function () {
var $this = $(this);
// remove padding on <table> to fix issue #7
$this.css('padding', 0);
base.$originalHeader = $('thead:first', this);
base.$clonedHeader = base.$originalHeader.clone();
$this.trigger('clonedHeader.' + name, [base.$clonedHeader]);
base.$clonedHeader.addClass('tableFloatingHeader');
base.$clonedHeader.css('display', 'none');
base.$originalHeader.addClass('tableFloatingHeaderOriginal');
base.$originalHeader.after(base.$clonedHeader);
base.$printStyle = $('<style type="text/css" media="print">' +
'.tableFloatingHeader{display:none !important;}' +
'.tableFloatingHeaderOriginal{position:static !important;}' +
'</style>');
$('head').append(base.$printStyle);
});
base.setOptions(options);
base.updateWidth();
base.toggleHeaders();
base.bind();
};
base.destroy = function () {
base.$el.unbind('destroyed', base.teardown);
base.teardown();
};
base.teardown = function () {
if (base.isSticky) {
base.$originalHeader.css('position', 'static');
}
$.removeData(base.el, 'plugin_' + name);
base.unbind();
base.$clonedHeader.remove();
base.$originalHeader.removeClass('tableFloatingHeaderOriginal');
base.$originalHeader.css('visibility', 'visible');
base.$printStyle.remove();
base.el = null;
base.$el = null;
};
base.bind = function () {
base.$scrollableArea.on('scroll.' + name, base.toggleHeaders);
if (!base.isWindowScrolling) {
base.$window.on('scroll.' + name + base.id, base.setPositionValues);
base.$window.on('resize.' + name + base.id, base.toggleHeaders);
}
base.$scrollableArea.on('resize.' + name, base.toggleHeaders);
base.$scrollableArea.on('resize.' + name, base.updateWidth);
};
base.unbind = function () {
// unbind window events by specifying handle so we don't remove too much
base.$scrollableArea.off('.' + name, base.toggleHeaders);
if (!base.isWindowScrolling) {
base.$window.off('.' + name + base.id, base.setPositionValues);
base.$window.off('.' + name + base.id, base.toggleHeaders);
}
base.$scrollableArea.off('.' + name, base.updateWidth);
};
base.toggleHeaders = function () {
if (base.$el) {
base.$el.each(function () {
var $this = $(this),
newLeft,
newTopOffset = base.isWindowScrolling ? (
isNaN(base.options.fixedOffset) ? base.options.fixedOffset.outerHeight() : base.options.fixedOffset) : base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0),
offset = $this.offset(),
scrollTop = base.$scrollableArea.scrollTop() + newTopOffset,
scrollLeft = base.$scrollableArea.scrollLeft(),
scrolledPastTop = base.isWindowScrolling ? scrollTop > offset.top : newTopOffset > offset.top,
notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) < (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset));
if (scrolledPastTop && notScrolledPastBottom) {
newLeft = offset.left - scrollLeft + base.options.leftOffset;
base.$originalHeader.css({
'position': 'fixed',
'margin-top': base.options.marginTop,
'left': newLeft,
'z-index': 3 // #18: opacity bug
});
base.leftOffset = newLeft;
base.topOffset = newTopOffset;
base.$clonedHeader.css('display', '');
if (!base.isSticky) {
base.isSticky = true;
// make sure the width is correct: the user might have resized the browser while in static mode
base.updateWidth();
}
base.setPositionValues();
} else if (base.isSticky) {
base.$originalHeader.css('position', 'static');
base.$clonedHeader.css('display', 'none');
base.isSticky = false;
base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader));
}
});
}
};
base.setPositionValues = function () {
var winScrollTop = base.$window.scrollTop(),
winScrollLeft = base.$window.scrollLeft();
if (!base.isSticky || winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() || winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) {
return;
}
base.$originalHeader.css({
'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop),
'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft)
});
};
base.updateWidth = function () {
if (!base.isSticky) {
return;
}
// Copy cell widths from clone
if (!base.$originalHeaderCells) {
base.$originalHeaderCells = $('th,td', base.$originalHeader);
}
if (!base.$clonedHeaderCells) {
base.$clonedHeaderCells = $('th,td', base.$clonedHeader);
}
var cellWidths = base.getWidth(base.$clonedHeaderCells);
base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells);
// Copy row width from whole table
base.$originalHeader.css('width', base.$clonedHeader.width());
};
base.getWidth = function ($clonedHeaders) {
var widths = [];
$clonedHeaders.each(function (index) {
var width, $this = $(this);
if ($this.css('box-sizing') === 'border-box') {
width = $this[0].getBoundingClientRect().width; // #39: border-box bug
} else {
var $origTh = $('th', base.$originalHeader);
if ($origTh.css('border-collapse') === 'collapse') {
if (window.getComputedStyle) {
width = parseFloat(window.getComputedStyle(this, null).width);
} else {
// ie8 only
var leftPadding = parseFloat($this.css('padding-left'));
var rightPadding = parseFloat($this.css('padding-right'));
// Needs more investigation - this is assuming constant border around this cell and it's neighbours.
var border = parseFloat($this.css('border-width'));
width = $this.outerWidth() - leftPadding - rightPadding - border;
}
} else {
width = $this.width();
}
}
widths[index] = width;
});
return widths;
};
base.setWidth = function (widths, $clonedHeaders, $origHeaders) {
$clonedHeaders.each(function (index) {
var width = widths[index];
$origHeaders.eq(index).css({
'min-width': width,
'max-width': width
});
});
};
base.resetWidth = function ($clonedHeaders, $origHeaders) {
$clonedHeaders.each(function (index) {
var $this = $(this);
$origHeaders.eq(index).css({
'min-width': $this.css('min-width'),
'max-width': $this.css('max-width')
});
});
};
base.setOptions = function (options) {
base.options = $.extend({}, defaults, options);
base.$scrollableArea = $(base.options.scrollableArea);
base.isWindowScrolling = base.$scrollableArea[0] === window;
};
base.updateOptions = function (options) {
base.setOptions(options);
// scrollableArea might have changed
base.unbind();
base.bind();
base.updateWidth();
base.toggleHeaders();
};
// Run initializer
base.init();
}
// A plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[name] = function (options) {
return this.each(function () {
var instance = $.data(this, 'plugin_' + name);
if (instance) {
if (typeof options === 'string') {
instance[options].apply(instance);
} else {
instance.updateOptions(options);
}
} else if (options !== 'destroy') {
$.data(this, 'plugin_' + name, new Plugin(this, options));
}
});
};
})(jQuery, window);
body {
margin: 0 auto;
padding: 0 20px;
font-family: Arial, Helvetica, sans-serif;
font-size: 11px;
color: #555;
}
table {
border: 0;
padding: 0;
margin: 0 0 20px 0;
border-collapse: collapse;
}
th {
padding: 5px;
/* NOTE: th padding must be set explicitly in order to support IE */
text-align: right;
font-weight:bold;
line-height: 2em;
color: #FFF;
background-color: #555;
}
tbody td {
padding: 10px;
line-height: 18px;
border-top: 1px solid #E0E0E0;
}
tbody tr:nth-child(2n) {
background-color: #F7F7F7;
}
tbody tr:hover {
background-color: #EEEEEE;
}
td {
text-align: right;
}
td:first-child, th:first-child {
text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div style="width:3000px">some really really wide content goes here</div>
<table>
<thead>
<tr>
<th colspan="9">Companies listed on NASDAQ OMX Copenhagen.</th>
</tr>
<tr>
<th>Full name</th>
<th>CCY</th>
<th>Last</th>
<th>+/-</th>
<th>%</th>
<th>Bid</th>
<th>Ask</th>
<th>Volume</th>
<th>Turnover</th>
</tr>
</thead>
<tbody>
<tr>
<td>A.P. Møller...</td>
<td>DKK</td>
<td>33,220.00</td>
<td>760</td>
<td>2.34</td>
<td>33,140.00</td>
<td>33,220.00</td>
<td>594</td>
<td>19,791,910</td>
</tr>
<tr>
<td>A.P. Møller...</td>
<td>DKK</td>
<td>34,620.00</td>
<td>640</td>
<td>1.88</td>
<td>34,620.00</td>
<td>34,700.00</td>
<td>9,954</td>
<td>346,530,246</td>
</tr>
<tr>
<td>Carlsberg A</td>
<td>DKK</td>
<td>380</td>
<td>0</td>
<td>0</td>
<td>371</td>
<td>391.5</td>
<td>6</td>
<td>2,280</td>
</tr>
<tr>
<td>Carlsberg B</td>
<td>DKK</td>
<td>364.4</td>
<td>8.6</td>
<td>2.42</td>
<td>363</td>
<td>364.4</td>
<td>636,267</td>
<td>228,530,601</td>
</tr>
<tr>
<td>Chr. Hansen...</td>
<td>DKK</td>
<td>114.5</td>
<td>-1.6</td>
<td>-1.38</td>
<td>114.2</td>
<td>114.5</td>
<td>141,822</td>
<td>16,311,454</td>
</tr>
<tr>
<td>Coloplast B</td>
<td>DKK</td>
<td>809.5</td>
<td>11</td>
<td>1.38</td>
<td>809</td>
<td>809.5</td>
<td>85,840</td>
<td>69,363,301</td>
</tr>
<tr>
<td>D/S Norden</td>
<td>DKK</td>
<td>155</td>
<td>-1.5</td>
<td>-0.96</td>
<td>155</td>
<td>155.1</td>
<td>51,681</td>
<td>8,037,225</td>
</tr>
<tr>
<td>Danske Bank</td>
<td>DKK</td>
<td>69.05</td>
<td>2.55</td>
<td>3.83</td>
<td>69.05</td>
<td>69.2</td>
<td>1,723,719</td>
<td>115,348,068</td>
</tr>
<tr>
<td>DSV</td>
<td>DKK</td>
<td>105.4</td>
<td>0.2</td>
<td>0.19</td>
<td>105.2</td>
<td>105.4</td>
<td>674,873</td>
<td>71,575,035</td>
</tr>
<tr>
<td>FLSmidth & Co.</td>
<td>DKK</td>
<td>295.8</td>
<td>-1.8</td>
<td>-0.6</td>
<td>295.1</td>
<td>295.8</td>
<td>341,263</td>
<td>100,301,032</td>
</tr>
<tr>
<td>G4S plc</td>
<td>DKK</td>
<td>22.53</td>
<td>0.05</td>
<td>0.22</td>
<td>22.53</td>
<td>22.57</td>
<td>190,920</td>
<td>4,338,150</td>
</tr>
<tr>
<td>Jyske Bank</td>
<td>DKK</td>
<td>144.2</td>
<td>1.4</td>
<td>0.98</td>
<td>142.8</td>
<td>144.2</td>
<td>78,163</td>
<td>11,104,874</td>
</tr>
<tr>
<td>Københavns ...</td>
<td>DKK</td>
<td>1,580.00</td>
<td>-12</td>
<td>-0.75</td>
<td>1,590.00</td>
<td>1,620.00</td>
<td>82</td>
<td>131,110</td>
</tr>
<tr>
<td>Lundbeck</td>
<td>DKK</td>
<td>103.4</td>
<td>-2.5</td>
<td>-2.36</td>
<td>103.4</td>
<td>103.8</td>
<td>157,162</td>
<td>16,462,282</td>
</tr>
<tr>
<td>Nordea Bank</td>
<td>DKK</td>
<td>43.22</td>
<td>-0.06</td>
<td>-0.14</td>
<td>43.22</td>
<td>43.25</td>
<td>167,520</td>
<td>7,310,143</td>
</tr>
<tr>
<td>Novo Nordisk B</td>
<td>DKK</td>
<td>552.5</td>
<td>-3.5</td>
<td>-0.63</td>
<td>550.5</td>
<td>552.5</td>
<td>843,533</td>
<td>463,962,375</td>
</tr>
<tr>
<td>Novozymes B</td>
<td>DKK</td>
<td>805.5</td>
<td>5.5</td>
<td>0.69</td>
<td>805</td>
<td>805.5</td>
<td>152,188</td>
<td>121,746,199</td>
</tr>
<tr>
<td>Pandora</td>
<td>DKK</td>
<td>39.04</td>
<td>0.94</td>
<td>2.47</td>
<td>38.8</td>
<td>39.04</td>
<td>350,965</td>
<td>13,611,838</td>
</tr>
<tr>
<td>Rockwool In...</td>
<td>DKK</td>
<td>492</td>
<td>0</td>
<td>0</td>
<td>482</td>
<td>492</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Rockwool In...</td>
<td>DKK</td>
<td>468</td>
<td>12</td>
<td>2.63</td>
<td>465.2</td>
<td>468</td>
<td>9,885</td>
<td>4,623,850</td>
</tr>
<tr>
<td>Sydbank</td>
<td>DKK</td>
<td>95</td>
<td>0.05</td>
<td>0.05</td>
<td>94.7</td>
<td>95</td>
<td>103,438</td>
<td>9,802,899</td>
</tr>
<tr>
<td>TDC</td>
<td>DKK</td>
<td>43.6</td>
<td>0.13</td>
<td>0.3</td>
<td>43.5</td>
<td>43.6</td>
<td>845,110</td>
<td>36,785,339</td>
</tr>
<tr>
<td>Topdanmark</td>
<td>DKK</td>
<td>854</td>
<td>13.5</td>
<td>1.61</td>
<td>854</td>
<td>855</td>
<td>38,679</td>
<td>32,737,678</td>
</tr>
<tr>
<td>Tryg</td>
<td>DKK</td>
<td>290.4</td>
<td>0.3</td>
<td>0.1</td>
<td>290</td>
<td>290.4</td>
<td>94,587</td>
<td>27,537,247</td>
</tr>
<tr>
<td>Vestas Wind...</td>
<td>DKK</td>
<td>90.15</td>
<td>-4.2</td>
<td>-4.45</td>
<td>90.1</td>
<td>90.15</td>
<td>1,317,313</td>
<td>121,064,314</td>
</tr>
<tr>
<td>William Dem...</td>
<td>DKK</td>
<td>417.6</td>
<td>0.1</td>
<td>0.02</td>
<td>417</td>
<td>417.6</td>
<td>64,242</td>
<td>26,859,554</td>
</tr>
</tbody>
</table>
<div style="height: 4000px">lots of content down here...</div>
我喜欢马克西米利安·希尔斯的回答,但有一些问题:
为了消除闪烁,我使用超时来等待用户完成滚动,然后应用转换-因此在滚动过程中标题不可见。
我也使用jQuery编写了此代码,其优点之一是jQuery应该为您处理供应商前缀
var isScrolling, lastTop, lastLeft, isLeftHidden, isTopHidden;
//Scroll events don't bubble https://stackoverflow.com/a/19375645/150342
//so can't use $(document).on("scroll", ".table-container-fixed", function (e) {
document.addEventListener('scroll', function (event) {
var $container = $(event.target);
if (!$container.hasClass("table-container-fixed"))
return;
//transform needs to be applied to th for Edge and IE
//in this example I am also fixing the leftmost column
var $topLeftCell = $container.find('table:first > thead > tr > th:first');
var $headerCells = $topLeftCell.siblings();
var $columnCells = $container
.find('table:first > tbody > tr > td:first-child, ' +
'table:first > tfoot > tr > td:first-child');
//hide the cells while returning otherwise they show on top of the data
if (!isLeftHidden) {
var currentLeft = $container.scrollLeft();
if (currentLeft < lastLeft) {
//scrolling left
isLeftHidden = true;
$topLeftCell.css('visibility', 'hidden');
$columnCells.css('visibility', 'hidden');
}
lastLeft = currentLeft;
}
if (!isTopHidden) {
var currentTop = $container.scrollTop();
if (currentTop < lastTop) {
//scrolling up
isTopHidden = true;
$topLeftCell.css('visibility', 'hidden');
$headerCells.css('visibility', 'hidden');
}
lastTop = currentTop;
}
// Using timeout to delay transform until user stops scrolling
// Clear timeout while scrolling
window.clearTimeout(isScrolling);
// Set a timeout to run after scrolling ends
isScrolling = setTimeout(function () {
//move the table cells.
var x = $container.scrollLeft();
var y = $container.scrollTop();
$topLeftCell.css('transform', 'translate(' + x + 'px, ' + y + 'px)');
$headerCells.css('transform', 'translateY(' + y + 'px)');
$columnCells.css('transform', 'translateX(' + x + 'px)');
isTopHidden = isLeftHidden = false;
$topLeftCell.css('visibility', 'inherit');
$headerCells.css('visibility', 'inherit');
$columnCells.css('visibility', 'inherit');
}, 100);
}, true);
该表与class一起包装在div中table-container-fixed
。
.table-container-fixed{
overflow: auto;
height: 400px;
}
我将border-collapse设置为单独的,因为否则会在翻译过程中丢失边框,并且我删除了表格上的边框以阻止内容显示在滚动过程中边框刚好位于其上方的单元格上方。
.table-container-fixed > table {
border-collapse: separate;
border:none;
}
我将th
背景设为白色以覆盖下面的单元格,并添加了一个与表格边框匹配的边框-使用Bootstrap对其进行样式设置并滚动到视图之外。
.table-container-fixed > table > thead > tr > th {
border-top: 1px solid #ddd !important;
background-color: white;
z-index: 10;
position: relative;/*to make z-index work*/
}
.table-container-fixed > table > thead > tr > th:first-child {
z-index: 20;
}
.table-container-fixed > table > tbody > tr > td:first-child,
.table-container-fixed > table > tfoot > tr > td:first-child {
background-color: white;
z-index: 10;
position: relative;
}
使用最新版本的jQuery,并包含以下JavaScript代码。
$(window).scroll(function(){
$("id of the div element").offset({top:$(window).scrollTop()});
});
这不是固定标题行的精确解决方案,但是我创建了一种相当巧妙的方法,可以在整个长表中重复标题行,但仍保持排序的能力。
这个简洁的小选项需要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);
});
很多人似乎正在寻找这个答案。我发现它埋在这里的另一个问题的答案中:在两个不同框架中的表之间同步列宽,等等
在我尝试过的数十种方法中,这是我发现的唯一一种可靠地工作的方法,该方法可以使您拥有底部宽度与标题表相同的滚动底部表。
这是我的操作方法,首先,我对上面的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插件,以及此处的Google Code项目https://code.google.com/p/js-scroll-table-header/issues/detail?id=2
其他涉及克隆表的解决方案,性能差或无法正常工作在所有情况下均不起作用。
不需要这些过于复杂的解决方案。只需像下面的示例那样制作两个表,然后像这里所述的那样调用 setHeaderTableWidth函数,然后就可以完成工作了。
如果这对您不起作用,则可能是您正在使用CSS框大小设置属性,需要正确设置它。偶然弄乱CSS内容很容易。有很多事情可能出问题,所以请注意这一点。这种方法对我有用。
这是我们最终使用的解决方案(为了处理某些极端情况和旧版本的Internet Explorer,我们最终还淡出了滚动条的标题栏,然后在滚动结束时淡出了标题栏,但在Firefox和WebKit浏览器中此解决方案仅能正常工作,它假定有border-collapse:崩溃。
该解决方案的关键是,一旦您应用border-collapse,CSS转换就可以在标头上工作,因此只需拦截滚动事件并正确设置转换即可。您无需重复任何操作。缺少在浏览器中正确实现的这种行为,很难想象会有一个更轻便的解决方案。
JSFiddle:http : //jsfiddle.net/podperson/tH9VU/2/
它实现为一个简单的jQuery插件。您只需通过$('thead')。sticky()之类的电话使thead保持粘性,它们就会四处徘徊。它适用于页面上的多个表以及位于大表中间的头部。
$.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();
这是对马克西米利安·希尔斯(Maximilian Hils)发布的答案的改进的答案。
此版本可在Internet Explorer 11中正常运行,而不会闪烁:
var headerCells = tableWrap.querySelectorAll("thead td");
for (var i = 0; i < headerCells.length; i++) {
var headerCell = headerCells[i];
headerCell.style.backgroundColor = "silver";
}
var lastSTop = tableWrap.scrollTop;
tableWrap.addEventListener("scroll", function () {
var stop = this.scrollTop;
if (stop < lastSTop) {
// Resetting the transform for the scrolling up to hide the headers
for (var i = 0; i < headerCells.length; i++) {
headerCells[i].style.transitionDelay = "0s";
headerCells[i].style.transform = "";
}
}
lastSTop = stop;
var translate = "translate(0," + stop + "px)";
for (var i = 0; i < headerCells.length; i++) {
headerCells[i].style.transitionDelay = "0.25s";
headerCells[i].style.transform = translate;
}
});
我开发了一个简单的轻量级jQuery插件,用于将格式正确的HTML表转换为具有固定表头和列的可滚动表。
该插件可以很好地使固定部分与可滚动部分的像素间匹配。此外,您还可以冻结水平滚动时始终在视图中显示的列数。
演示和文档:http : //meetselva.github.io/fixed-table-rows-cols/
GitHub存储库:https : //github.com/meetselva/fixed-table-rows-cols
以下是带有固定标题的简单表的用法,
$(<table selector>).fxdHdrCol({
width: "100%",
height: 200,
colModal: [{width: 30, align: 'center'},
{width: 70, align: 'center'},
{width: 200, align: 'left'},
{width: 100, align: 'center'},
{width: 70, align: 'center'},
{width: 250, align: 'center'}
]
});
<html>
<head>
<script src="//cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
<script>
function stickyTableHead (tableID) {
var $tmain = $(tableID);
var $tScroll = $tmain.children("thead")
.clone()
.wrapAll('<table id="tScroll" />')
.parent()
.addClass($(tableID).attr("class"))
.css("position", "fixed")
.css("top", "0")
.css("display", "none")
.prependTo("#tMain");
var pos = $tmain.offset().top + $tmain.find(">thead").height();
$(document).scroll(function () {
var dataScroll = $tScroll.data("scroll");
dataScroll = dataScroll || false;
if ($(this).scrollTop() >= pos) {
if (!dataScroll) {
$tScroll
.data("scroll", true)
.show()
.find("th").each(function () {
$(this).width($tmain.find(">thead>tr>th").eq($(this).index()).width());
});
}
} else {
if (dataScroll) {
$tScroll
.data("scroll", false)
.hide()
;
}
}
});
}
$(document).ready(function () {
stickyTableHead('#tMain');
});
</script>
</head>
<body>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
<table id="tMain" >
<thead>
<tr>
<th>1</th> <th>2</th><th>3</th> <th>4</th><th>5</th> <th>6</th><th>7</th> <th>8</th>
</tr>
</thead>
<tbody>
<tr><td>11111111111111111111111111111111111111111111111111111111</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
</tbody>
</table>
</body>
</html>
@Daniel Waltrip答案的补充。表需要用div括起来position: relative
才能使用position:sticky
。所以我想在这里发布我的示例代码。
的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>
演示版