HTML table with fixed headers?
是否有跨浏览器的CSS / JavaScript技术来显示较长的HTML表,以使列标题在屏幕上保持固定,并且不随表主体滚动。 考虑一下Microsoft Excel中的"冻结窗格"效果。
我希望能够滚动浏览表的内容,但始终能够看到顶部的列标题。
- 尝试以下操作:具有固定标题EDIT的纯CSS可滚动表:如示例所示,该控件应在Internet Explorer 7中工作:具有固定标题EDIT的HTML滚动表2:我发现了几个可能有用的额外链接:-愚蠢固定标头-具有某些限制的jQuery插件。 -[固定表格标题](cross-browser.com/x/examp
- 香港专业教育学院遇到了许多解决方案,通常可以正常工作,但没有一个工作滚动div。我的意思是,您的表位于可滚动div内,而您仍然希望表头仍位于该div内。香港专业教育学院解决了这一点,并在这里分享解决方案。
- 解决方案:stackoverflow.com/questions/2382083/fix-thead-on-page-scroll/
- github.com/karaxuna/fixed-table-header
-
在2018年,所有浏览器都可以使用以下简单解决方案:
thead th { position: sticky; top: 0; } 。 Safari需要供应商前缀:-webkit-sticky - @DanielWaltrip,您应该为它添加一个答案,以便它可以被投票到首位-所有其他答案在位置上都是多余的:粘性现在是更好的支持
- 做完了! stackoverflow.com/a/52637779/111635
-
sticky 似乎是最好的解决方案。在类似问题上也有一个很好的答案,并提供了一个有用的示例:stackoverflow.com/a/50516259/982107
这可以用四行代码来彻底解决。
如果您只关心现代浏览器,则可以使用CSS转换轻松实现固定标头。听起来很奇怪,但效果很好:
- HTML和CSS保持不变。
- 没有外部JavaScript依赖项。
- 四行代码。
- 适用于所有配置(表布局:固定等)。
1 2 3 4 | document.getElementById("wrap").addEventListener("scroll", function(){ var translate ="translate(0,"+this.scrollTop+"px)"; this.querySelector("thead").style.transform = translate; }); |
除InternetExplorer8-外,对CSS转换的支持广泛可用。
这是完整的示例供参考:
1 2 3 4 | document.getElementById("wrap").addEventListener("scroll",function(){ var translate ="translate(0,"+this.scrollTop+"px)"; this.querySelector("thead").style.transform = translate; }); |
1 2 3 4 5 6 7 8 9 10 11 12 | /* Your existing container */ #wrap { overflow: auto; height: 400px; } /* CSS for demo */ td { background-color: green; width: 200px; height: 100px; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <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> |
- 您需要添加供应商前缀才能在某些浏览器(例如IE9,Safari,某些移动浏览器)中正??常工作,对吗?另外,即使有前缀,我也无法在IE9中使用它,但是也许我做错了:jsfiddle
- 我必须说,尽管有我先前的评论,但这是我所见过的完美解决方案中最接近的事情。甚至水平滚动也是完美的(比我自己的解决方案更好)。这是一个带有边框(不能使用border-collapse)和一个滚动条的示例,该滚动条粘贴在表格而不是容器上:jsfiddle
- 我将很高兴知道如何将此技术用于固定柱!
- 不幸的是,无论有没有供应商前缀,它在IE 11中都不适合我:(
- 找出来,它可以工作,但必须将转换应用于th / td,而不是thead。
- 很好的解决方案。谢谢!您还可以帮助固定第一列吗?
- @AlexAlexeev我也需要帮助。在过去的几个月中,您找到任何解决方案了吗?此解决方案+1,它是Ive找到的最好的100%。
- @MikeResoli是的,这是我来到的代码:jsfiddle.net/buduguru/m1jvyafz
-
@AlexAlexeev,您的解决方案很棒。谢谢。我注意到,生成的固定标题没有区分列的边框线。默认的CSS样式丢失。即使我添加了此内容...
$(this).addClass(border) 也会更改我在border类中传递的表的其余部分的字体,大小,颜色。但是,不向固定标题添加行。赞赏,关于如何解决此问题的任何投入 - @ user5249203您可以创建一个JSFiddle吗? :)
- 喜欢这个主意,在小提琴中效果很好。但是,在我的实现中,滚动性能非常糟糕。还有其他人要处理吗?
- @ user5249203我知道您在几个月前问过,但是我也遇到了同样的问题,这是由于边界崩溃造成的:请参阅:stackoverflow.com/questions/33777751/。
- 这么多小时的研究,您就解决了我们的难题。华丽。设法使它在所有浏览器中都能正常工作。
- 这不适用于任何版本的IE或Edge。这是一个基于@redheads注释的版本jsfiddle.net/n6o8ocwb/2
- 有人在为IE 11提供解决方案吗?不在那儿工作。
- @AlexAlexeev如果我有一个复杂的标头(包括2个标头行,具有rowpan和colspan属性),我该如何采用您的出色解决方案?谢谢
- @Maximilian Hils。不幸的是,我无法在5分钟后编辑最后一条评论,所以我修复了收件人?马克西米利安(Maximilian),当然还有任何其他可以建议的人::)
- 谢谢你似乎我们应该翻译th而不是thead,并使用querySelectorAll(th)进行翻译,以便IE和Edge正常工作。这在其他浏览器中也适用。但是,为什么TH的背景现在是透明的?即使在您的代码段中,我也看到标题标题后面的绿色显示。我想要一个不透明的标题,但是我很难使它变得不透明。任何帮助将不胜感激。
- 我非常喜欢这种解决方案。它是完美的,对用户来说就像浏览器本身支持固定的列标题一样。我遇到了边界崩溃错误(即:翻译导致边界消失)。我通过使用border-spacing来解决:0;而不是边界崩溃。
- 这个想法曾经有一个固定的表头和主要使用CSS的固定列。看到这里:stackoverflow.com/questions/45314977/
- 在手机上无法正常工作。可能是因为滚动事件不会立即触发。
- 出色的答案,适用于任何配置
-
惊人!我做了2次调整:1)我为表标题设置了
background-color ,例如th { background-color:#fff; } 以消除滚动时标题下方的重叠。 2)我从this.scrollTop (例如var translate ="translate(0,"+(this.scrollTop-3)+"px)"; )中减去了3,因为行在消失之前向上滚动了标题上方几个像素。我不确定这些是否是基于我其他标记的警告,但也许对其他人有用! (看着你,@ GregVeres!) -
有什么办法可以使
thead 和th 的边框与thead一起translate ? -
边框问题的解决方案:使用
border-spacing: 0; (而不是border-collapse ),然后仅对单元格设置border-bottom 和border-right ,以避免出现两个粗边框。当然,还应对表中的最后一行禁用border-right ,对表的最后一行禁用border-bottom 。 - 加,我讲得太早了。它在Chrome上绝对可以完美运行,但是在其他浏览器上我却会忽悠。其他答案中提到的闪烁解决方案也可以,但是只能通过在滚动过程中"隐藏"标题来实现,虽然可以,但效果并不理想。令人难以置信的是,它很难解决这个绝对基本的UI要求...
-
哇!好的,经过更多搜索,似乎在2018年实际上是一个合适的解决方案。忘记所有这些魔术。只需使用以下CSS:
thead th { position: sticky; top: 0; } - 需要一个固定的身高,该如何解决100%的身高
-
这在固定表头中可用。也可以在IE11中使用,但只能在
上使用。谢谢。
一段时间以来,我一直在寻找解决方案,但发现大多数答案都不起作用或不适合我的情况,因此我用jQuery写了一个简单的解决方案。
这是解决方案概述:
- 克隆需要具有固定标题的表,然后将
原始副本上的克隆副本。- 从顶部桌子上取下桌子主体。
- 从底部表格中删除表格标题。
- 调整列宽。 (我们会跟踪原始列宽)
以下是可运行演示中的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46function scrolify(tblAsJQueryObject, height) {
var oTbl = tblAsJQueryObject;
// for very large tables you can remove the four lines below
// and wrap the table with in the mark-up and assign
// height and overflow property
var oTblDiv = $("");
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("");
// 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
});1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js">
<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>此解决方案可在Chrome和IE中使用。由于它基于jQuery,因此它也应该在其他受jQuery支持的浏览器中也可以使用。
- 当内容大于宽度时,如何解决该问题?
- @tetra td {max-width:30px; }这将使开发人员可以控制行的显示方式。
- 但是,如果某些标头单元中的内容比td单元中的内容长,该怎么办?我在IE7中尝试过,而width()破坏了一切。 IE8和IE9可以正常工作,但是...
- 不幸的是,如果您要求列的像素完美对齐,则此方法不起作用:jsbin.com/elekiq/1(源代码)。您会看到一些标题从应有的位置偏移了一点。如果您使用背景,效果会更加明显:jsbin.com/elekiq/2(源代码)。 (我一直按照同样的方式工作,在我的代码中遇到了这个问题,发现了你的想法,然后想:"哦,我想知道他是否为我解决了这个问题!"可悲的不是。:-))浏览器对于想要控制单元的宽度...
- 这似乎不适用于水平滚动-它创建了标题,但它超出了可滚动区域(可见),并且不随内容滚动。
-
这是可行的,但是会产生无效的HTML。除非您真的知道它在做什么,否则
.clone 方法很危险。 -
您还说
thead tr td 选择器是什么意思?根据您的标记,它看起来无效。 - 固定标题演示处于脱机状态,您可以修复它吗?
- @ M.Mimpen修复了演示网址。
- 调整窗口大小会导致问题:jsfiddle.net/2z7r4o96/3,这是我的问题:stackoverflow.com/questions/28412593/。请帮助我:)谢谢。
- 当您有一个需要水平滚动的表时,并且列的大小不同时,该演示也会中断。我写了一个解决这些极端情况的版本,也不需要jQuery:github.com/OliverJAsh/sticky-table-header
我刚刚完成一个jQuery插件的组装,该插件将使用有效的HTML来获取有效的单个表(必须具有thead和tbody),并将输出具有固定页眉,可选固定页脚的表,该页脚可以是克隆的页眉,也可以是任何您选择的内容(分页等)。如果要利用较大的显示器,则在调整浏览器大小时,它还将调整表的大小。如果表的列不能全部适合视图,则另一个附加功能是可以侧向滚动。
http://fixedheadertable.com/
在github上:http://markmalek.github.com/Fixed-Header-Table/
设置非常容易,您可以为其创建自己的自定义样式。它还在所有浏览器中使用圆角。请记住,我刚刚发布了它,因此从技术上来说它仍然是beta版,我要解决的问题很少。
它适用于Internet Explorer 7,Internet Explorer 8,Safari,Firefox和Chrome。
- 谢谢!我今天下班回家时添加了一个新版本。这是我的博客条目的链接,其中包含即时消息:fixedheadertable.mmalek.com/2009/10/07/
- 这次真是万分感谢。我知道这个问题已有一年多的历史了,但即使冒着搅动已解决的淤泥的风险,我也想告诉您,您的工作受到赞赏
- 在您的演示中,宽度不在ie6中:-(表头和主体未对齐。
- 最新版本在IE6中不起作用。我不再支持IE6。
- 上面的链接已断开,fixedheadertable.com正常工作
- 我编辑了答案以显示新的URL。
- 马克(Mark)伟大的工作-不幸的是,移动设备(iPad,Android平板电脑)中固定标题和列的滚动存在一些问题-当我滚动那些固定部分的内容时-当我停止滚动并点击表格后,将零件"跳"到正确的位置-是否有简单的方法可以解决此问题?
- 标记-此插件不适用于jQuery 1.9.1。有计划更新吗?我也无法在任何版本的jQuery中使用浏览器调整表的大小。看起来很有希望,谢谢。
- 如果(像我一样)无法正常工作,请确保正确添加CSS,请参阅此问题和解答。
我还创建了一个可解决此问题的插件。我的项目jQuery.floatThead已经存在了4年多了,并且非常成熟。
它不需要外部样式,也不希望您的表以任何特定方式设置样式。它支持InternetExplorer9 +和Firefox / Chrome。
目前(2018-05)它具有:
405 commits and 998 stars on GitHub
这里的很多(不是全部)答案都是快速的技巧,它们可能已经解决了一个人遇到的问题,但是并不能在每个桌子上都起作用。
其他一些插件较旧,可能与InternetExplorer兼容,但在Firefox和Chrome上将无法使用。
- 很棒的插件,支持嵌套表和偏移量。
- 大。非常感谢。该插件在Firefox 45.2,Chromium 51和IE 11中运行良好。此外,它不会干扰在同一页面上构建的许多JS和jQuery代码。
- 谢谢。我很高兴地向您报告,该项目每4个月收到1个错误报告。我没有做出很多重大更改。它非常坚固且有效。
TL; DR如果您以现代浏览器为目标,并且没有过分的样式需求:http://jsfiddle.net/dPixie/byB9d/3/ ...尽管前四个版本也很不错,但该版本在处理宽度方面要好得多。
大家好消息!
随着HTML5和CSS3的发展,现在已经成为可能,至少对于现代浏览器而言是这样。我想出的有点黑的实现可以在这里找到:http://jsfiddle.net/dPixie/byB9d/3/。我已经在FX 25,Chrome 31和IE 10中对其进行了测试...
相关HTML(不过,在文档顶部插入HTML5文档类型):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68html,
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;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69<section class="positioned">
<table>
<thead>
<tr class="header">
<th>
Table attribute name
Table attribute name
</th>
<th>
Value
Value
</th>
<th>
Description
Description
</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>
</section>但是如何?
简单地说,您有一个表头,您可以通过将其设置为0px高将其隐藏,该表头还包含用作固定头的div。表格的容器在顶部留有足够的空间以容纳绝对定位的标题,并且带有滚动条的表格如您所愿。
上面的代码使用定位类绝对定位表(我在弹出式对话框中使用它),但是您也可以通过从容器中删除
positioned 类在文档流中使用它。但是...
这不是完美的。 Firefox拒绝将标题行设置为0px(至少我没有找到任何方法),但顽固地将其保持在至少4px……这不是一个大问题,但是取决于您的样式,它会与边框混淆等。
该表还使用了仿列方法,其中容器本身的背景色用作透明的标题div的背景。
摘要
总而言之,根据您的要求,可能会有样式问题,尤其是边框或复杂的背景。可计算性可能还存在一些问题,我尚未在各种浏览器中对其进行过检查(如果您尝试过,请在您的经验中发表评论),但是我没有找到类似的东西,因此我认为值得发布反正...
- 如果缩小窗口的宽度直到开始水平滚动,则标题将不会与主体水平滚动。真是
- @dlaliberte-好吧,因为标题和表实际上是两个不同的元素,所以您可能会感到奇怪。但是我的示例不允许表列上溢出,并且标题通常比表内容更易于控制。就是说,如果您导致标题"溢出",它将突出显示在表格的右侧并严重损坏。您可以通过在表上设置最小宽度来解决此问题,并迫使它也溢出页面。但是它是一个hack,因此永远不会是完美的...
- 值得指出的是,这需要一种可以指定固定高度表的设计。
-
@Cheekysoft-不,表格和行的内容可以自由流动。容器(在我的示例中为
元素)需要进行高度限制,以强制其溢出并显示滚动。任何会使容器溢出的布局都可以使用。如果您发现没有这种情况,请发布小提琴的链接。 -
硬编码的
padding-top 值还意味着,如果表格标题文本在多行上,它将显示在表格单元格的顶部。可惜,因为这在大多数时候都像一种魅力。th 中的div 真是个不错的技巧,可以解决大多数其他解决方案所具有的列大小问题。
从CSS规范之外解决此问题的所有尝试都笼罩着我们真正想要的东西:在THEAD的隐含承诺下交付。
很长一段时间以来,这个表格冻结标题问题一直是HTML / CSS的一个开放式伤口。
在理想的情况下,将有一个纯CSS解决此问题的方法。不幸的是,似乎没有一个合适的解决方案。
有关此主题的相关标准的讨论包括:
- www.style上的粘性定位建议:http://lists.w3.org/Archives/Public/www-style/2012Jun/0627.html
- Tab Atkins关于位置根,位置包含或位置限制的建议:http://www.xanthir.com/blog/b48H0
更新:Firefox在版本32中发布了
position:sticky 。每个人都赢了!- 以同样的方式拥有狐狸柱真是太好了
- 回覆。 Firefox和position:sticky,不适用于表标题:bugzilla.mozilla.org/show_bug.cgi?id=925259#c8 ...该错误的补丁明确指出:"我们目前不支持内部表元素的相对定位,因此我们也将其排除在粘性定位之外。"
-
现在,该功能适用??于所有浏览器:
thead th { position: sticky; top: 0; } 。我们可以更新此答案以清楚地说明这一点吗? - @DanielWaltrip所有浏览器? stackoverflow.com/a/37646284/3640407 MSIE仍然比Edge多
- 有道理。根据caniuse.com/#search=position%3Asticky,全球86%的Web用户都支持该功能。
这是固定表头的jQuery插件。它允许整个页面滚动,并在到达顶部时冻结标题。它与Twitter Bootstrap表很好地配合。
GitHub存储库:https://github.com/oma/table-fixed-header
它不只滚动表内容。寻找其他工具,作为其他答案之一。您可以决定最适合您的情况。
- Bummer-示例链接已死。"糟糕!Denne siden ble ikke funnet ..."希望将代码粘贴到此处。
- 是的...对此感到抱歉。删除了链接。该项目不再维护
- 不用担心-我尝试了其中一些预制的解决方案-没有一个可以使用超过屏幕宽度的flex-col-width表。我写了自己的解决方案。
这里发布的大多数解决方案都需要jQuery。如果您正在寻找独立于框架的解决方案,请尝试使用Grid:http://www.matts411.com/post/grid/
它托管在Github上:https://github.com/mmurph211/Grid
它不仅支持固定的页眉,还支持固定的左列和页脚。
- 如果我满足您的需求,这真是太好了,我今天就玩了。不幸的是,它实际上是一个矩形网格(顾名思义,实际上),而不是真正的表格,其行高由内容调整。设置单个行的样式似乎很困难。我无法创建一个斑马条纹表,但并没有非常努力,因为我的需求实际上更加复杂。无论如何,很好的工作。
- 嘿,我认识你!我们似乎写了非常相似的屎(github.com/mkoryak/floatThead)-Misha
更精致的纯CSS滚动表到目前为止,我见过的所有纯CSS解决方案(尽管它们可能很聪明)都缺乏一定程度的改进,或者只是在某些情况下无法正常工作。因此,我决定创建自己的...
特征:
-
它是纯CSS,因此不需要jQuery(或完全不需要任何JavaScript代码)
物) - 您可以将表格宽度设置为百分比(也称为"流体")或固定值,也可以由内容确定其宽度(也称为"自动")
- 列宽也可以是可变的,固定的或自动的。
- 列永远不会因水平滚动而与标题不对齐(这是我所见过的其他所有基于CSS的解决方案中都不需要固定宽度的问题)。
- 与所有流行的桌面浏览器兼容,包括从Internet Explorer返回8版本的浏览器
- 清洁,抛光的外观;没有马虎的1像素间隙或边框未对齐;在所有浏览器中看起来都一样
以下是一些小提琴,它们显示了流畅和自动宽度选项:
-
流体的宽度和高度(适合屏幕大小):jsFiddle(请注意,在此配置中,滚动条仅在需要时显示,因此您可能必须缩小框架才能看到它)
-
自动宽度,固定高度(更易于与其他内容集成):jsFiddle
"自动宽度,固定高度"配置可能有更多用例,因此我将在下面发布代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136/* 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 */1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35<table>
<caption>Top Caption</caption>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th>
<!-- More versatile way of doing column label; requires two identical copies of label -->
Column 4Column 4
</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>
Faux bottom caption
<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->我用来冻结标题行的方法与d-Pixie相似,因此请参阅其帖子以获取解释。这项技术存在很多错误和局限性,只能通过堆额外的CSS和一个或多个div容器来解决。
- 这个答案很被人赞赏!我花了几天的时间试图找到其他解决方案,以解决我特别烦人的情况。他们每个人都无法以一种或另一种方式保持一致。终于做到了!乍一看似乎过于复杂,但是一旦掌握了它,就很棒。最后,当不使用流体宽度时,您可以删除大量不需要的东西。
- @JustinSane很高兴您喜欢它!我想缺少欣赏是由于它与Maximilian Hils的解决方案共享页面。如果您不反对使用少量JS,则一定要检查一下。
- 该死的,那确实是一个几乎完美的解决方案。无论如何,我一直在使用jQuery,试图在找到您的jQuery之前使其与它一起使用(通过您对另一个问题的评论)。没想到要滚动监听器并翻译...好吧,他们说想出一个简单的解决方案需要天才。.;??)我完成了该项目,并且在没有js的情况下也可以完美地工作,但我会在未来牢记这一点。尽管如此,还是要赞美您!
- 一个小问题,但是如果您使用不同的系统颜色,则可以看到除了标题之外,没有为其他任何内容设置文本颜色,但是表格背景具有显式的背景颜色。我在这张桌子的白色和灰色背景上有黄色的文字。
- @MattArnold固定。谢谢!
CSS属性
position: sticky 在大多数现代浏览器中都有很好的支持(Edge出现问题,请参见下文)。这使我们可以很轻松地解决固定标头的问题:
1thead th { position: sticky; top: 0; }Safari需要供应商前缀:
-webkit-sticky 。对于Firefox,我必须将
min-height: 0 添加到父元素之一。我完全忘记了为什么需要这样做。最不幸的是,Microsoft Edge实施似乎只是半成品。至少,我在测试中有一些闪烁且未对齐的表格单元。该桌子仍然可用,但存在重大美学问题。
-
对具有
overflow: scroll; ,overflow-x: scroll; 或overflow-y: scroll; 的div内的表使用position: sticky; 。在现代浏览器中,似乎是固定表标题和列的最佳和最简单的解决方案。这个答案需要投票给最高。
一个简单的jQuery插件这是Mahes解决方案的一种变体。您可以像
$('table#foo').scrollableTable(); 这样称呼它这个想法是:
-
将
thead 和tbody 拆分为单独的table 元素 - 使它们的单元格宽度再次匹配
-
将第二个
table 包裹在div.scrollable 中 -
使用CSS使
div.scrollable 实际滚动
CSS可能是:
1div.scrollable { height: 300px; overflow-y: scroll;}注意事项
- 显然,拆分这些表会使标记的语义更少。我不确定这对可访问性有什么影响。
- 此插件不处理页脚,多个页眉等。
- 我仅在Chrome版本20中对其进行了测试。
就是说,它适用于我的目的,您可以随意使用和修改它。
这是插件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23jQuery.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 = $('').addClass('scrollable');
$newTable.insertAfter($oldTable).wrap($scrollableDiv);
};- 不错的脚本,这个脚本在我的环境中效果最好。我在固定页脚支持下扩展了您的脚本,请查看下面的文章。
:)
不太干净,但是纯HTML / CSS解决方案。
1
2
3
4
5
6
7
8
9table {
overflow-x:scroll;
}
tbody {
max-height: /*your desired max height*/
overflow-y:scroll;
display:block;
}已针对IE8 +更新
JSFiddle示例- 好的解决方案,仅提及这些单元格是浮动的,因此根据内容可以具有不同的高度,如果设置它们的边框,则可以看到以下高度:jsfiddle.net/ZdeEH/15
支持固定页脚我扩展了Nathan的功能,以支持固定的页脚和最大高度。
另外,该函数将设置CSS本身,而您只需要支持宽度即可。用法:
固定高度:
1$('table').scrollableTable({ height: 100 });最大高度(如果浏览器支持CSS" max-height"选项):
1$('table').scrollableTable({ maxHeight: 100 });脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49jQuery.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 = $('').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 的情况下工作得很好:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25table{
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%
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141<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可滚动,并使用JavaScript将标头中的列宽设置为与数据中的宽度相同。我认为数据列的宽度需要固定而不是动态。
- 如果您关心可访问性,那么这将是失败的。
-
关于可访问性,也许我们可以用
和
上的样式替换div的使用?
对于那些尝试了Maximilian Hils给出的不错的解决方案但没有成功使其与Internet Explorer一起使用的人来说,我遇到了同样的问题(InternetExplorer11),并找出了问题所在。
在InternetExplorer11中,样式转换(至少对于转换而言)不适用于
。我通过在循环中将样式应用于所有 来解决了这个问题。那行得通。我的JavaScript代码如下所示: 1
2
3
4
5
6
7document.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。首先,我认为这是因为它没有
,但是即使我强迫它具有 ,它也不起作用。然后我发现了我上面写的。 这是一个非常简单的解决方案。在Chrome上它是完美的,在Firefox上有点生涩,而在InternetExplorer上则更加生涩。但总而言之,这是一个很好的解决方案。
我意识到这个问题允许使用JavaScript,但这是我处理过的纯CSS解决方案,它还允许表格水平扩展。它已通过InternetExplorer10以及最新的Chrome和Firefox浏览器进行了测试。底部的jsFiddle链接。
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26Putting 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.
<table>
<colgroup>
<col class="col1"></col>
<col class="col2"></col>
</colgroup>
<thead>
<th class="header-col1">Header 1</th>
<th class="header-col2">Header 2</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>和CSS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62table{
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/
这是对马克西米利安·希尔斯(Maximilian Hils)发布的答案的改进的答案。
这可以在InternetExplorer11中正常运行,而不会闪烁:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22var 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;
}
});
我希望能早点找到@Mark的解决方案,但是在看到这个问题之前,我去写了自己的解决方案...
我的是一个非常轻量级的jQuery插件,它支持固定的页眉,页脚,列跨度(colspan),调整大小,水平滚动以及滚动开始之前要显示的可选行数。
jQuery.scrollTableBody(GitHub)
只要您有一个带有正确的
,和(可选) 的表,您要做的就是: 1$('table').scrollTableBody();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104<html>
<head>
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js">
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');
});
</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>
我开发了一个简单的轻量级jQuery插件,用于将格式正确的HTML表转换为具有固定表头和列的可滚动表。
该插件可以很好地将固定部分与可滚动部分的像素对像素匹配。此外,您还可以冻结水平滚动时始终在视图中显示的列数。
演示和文档:http://meetselva.github.io/fixed-table-rows-cols/
GitHub存储库:https://github.com/meetselva/fixed-table-rows-cols
以下是带有固定标题的简单表的用法,
1
2
3
4
5
6
7
8
9
10
11$(<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表格"?
- @PeterMortensen应该是"格式正确的HTML"。编辑,谢谢。
很多人似乎正在寻找这个答案。我发现它埋在这里的另一个问题的答案中:在两个不同框架中的表之间同步列宽,等等
在我尝试过的数十种方法中,这是我发现的唯一一种可靠地工作的方法,该方法可以使您拥有底部宽度与标题表相同的滚动底表。
这是我的操作方法,首先,我对上面的jsfiddle进行了改进,以创建此函数,该函数可同时在
td 和th 上使用(以防其他人使用th 设置其标题行的样式)。1
2
3
4
5
6
7
8
9var 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 ,以便在顶部表中为滚动条留出空间,如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<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>
<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>然后执行以下操作:
1
2
3
4setHeaderTableWidth('headertable1', 'basetable1');
$(window).resize(function () {
setHeaderTableWidth('headertable1', 'basetable1');
});这是我在StackOverflow上发现的唯一解决方案,该解决方案可以解决许多已发布的类似问题,并且可以在所有情况下使用。
例如,我尝试了不适用于durandal的jQuery stickytables插件,以及此处的Google Code项目https://code.google.com/p/js-scroll-table-header/issues/detail?id=2
其他涉及克隆表的解决方案,性能差或无法正常工作在所有情况下均不起作用。
不需要这些过于复杂的解决方案。只需像下面的示例一样制作两个表,然后像这里所述的那样调用setHeaderTableWidth函数,即可完成工作。
如果这对您不起作用,则可能是您正在使用CSS box-sizing属性,需要正确设置它。偶然弄乱CSS内容很容易。有很多事情可能会出错,因此请注意/小心。这种方法对我有用。
这是我们最终使用的解决方案(为了处理某些极端情况和旧版本的InternetExplorer,我们最终还淡出了滚动条的标题栏,然后在滚动结束时淡出了标题栏,但是在Firefox和WebKit浏览器中,解决方案是可行的,它假设有边界崩溃:崩溃。
该解决方案的关键是,一旦应用了边框折叠,CSS转换就可以在标头上工作,因此只需拦截滚动事件并正确设置转换即可。您无需重复任何操作。缺少在浏览器中正确实现的这种行为,很难想象会有一个更轻便的解决方案。
JSFiddle:http://jsfiddle.net/podperson/tH9VU/2/
它实现为一个简单的jQuery插件。您只需通过$('thead')。sticky()之类的电话使thead变得很粘,它们就会在周围徘徊。它适用于页面上的多个表以及位于大表中间的头部。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36$.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();- 一个好的解决方案,但是如何在列之间包括列边界(都在固定标题中,对齐到td数据)?
- 我不确定我是否理解您的问题。 border-collapse不会阻止您使用边框,边距等,它只是删除了过去的伏都表指标。
-
将
border: 2px solid red; 添加到th ,滚动,您将看到问题。我自己提出了这个更基本的解决方案:jsfiddle.net/x6pLcor9/19 - 将相同尺寸的边框添加到td,没有问题。我看不出你的意思。您的版本更干净,并且不使用jQuery,因此Id无疑今天可以使用更多类似的功能。 (不过,坦白地说,我认为今天我根本不使用桌子。)
我喜欢马克西米利安·希尔斯(Maximillian Hils)的回答,但遇到了一些问题:
- 除非将变换应用于Edge,否则变换在Edge或IE中不起作用
- 在Edge和IE中滚动时标题闪烁
- 我的表是使用ajax加载的,所以我想附加到窗口滚动事件,而不是包装器的滚动事件
为了摆脱闪烁,我使用超时来等待用户完成滚动,然后应用转换-因此在滚动过程中标题不可见。
我也使用jQuery编写了此代码,其优点之一是jQuery应该为您处理供应商前缀
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61var 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);该表包装在具有
table-container-fixed 类的div中。1
2
3
4.table-container-fixed{
overflow: auto;
height: 400px;
}我将border-collapse设置为单独的,因为否则会在翻译过程中丢失边框,并且我删除了表格上的边框以阻止内容显示在滚动过程中边框刚好位于其上方的单元格上方。
1
2
3
4.table-container-fixed > table {
border-collapse: separate;
border:none;
}我将
th 背景设置为白色以覆盖下面的单元格,并添加了与表格边框匹配的边框-使用Bootstrap设置样式并滚动到视图之外。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17.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代码。
1
2
3$(window).scroll(function(){
$("id of the div element").offset({top:$(window).scrollTop()});
});- 这似乎不起作用。也许您可以澄清您要我们做什么?
- 什么div?在这里谈论桌子
我发现了这种解决方法-将表头行移到带有数据的表上方的表中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57<html>
<head>
Fixed header
<style>
table td {width:75px;}
</style>
</head>
<body>
<table border="1">
<tr>
<td>header 1</td>
<td>header 2</td>
<td>header 3</td>
</tr>
</table>
<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>
</body>
</html>- 适用于小型表,但如果水平滚动,则此解决方案将不起作用。
- 由于表的列不对齐,它也将无法正常工作。在这里,您要强制td的宽度,但我们不能这样做...
通过将StickyTableHeaders jQuery插件应用于表,当您向下滚动时,列标题将停留在视口的顶部。
例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277$(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);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39body {
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;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
some really really wide content goes here
<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>
lots of content down here...
这不是固定标题行的精确解决方案,但我创建了一种相当巧妙的方法,可以在整个长表中重复标题行,但仍保持排序的能力。
这个简洁的小选项需要jQuery
tablesorter 插件。运作方式如下:的HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119<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的
1
2
3
4
5
6
7
8
9
10
11
12
13// 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);
});
Copyright © 码农家园 联系:[email protected]
- 克隆需要具有固定标题的表,然后将