我有一个解决方案,我可以通过使用次要的jQuery和CSS创建可修改页眉/页脚的可滚动表 - 但我正在寻找一种方法,使其成为跨浏览器兼容的仅CSS解决方案。
要明确的是,我要做的是使用仅一个table
标记(并且它是有效的子标记,colgroup
,col
, thead
,tbody
,tfoot
,tr
,th
,td
),但采用一组符合以下条件的CSS规则:
此代码示例:http://jsfiddle.net/TroyAlford/SNKfd/显示了我当前的方法。大多数JS只是用随机值填充表,但最后一部分是驱动左/右可滚动性的原因。
$tbody.bind('scroll', function(ev) {
var $css = { 'left': -ev.target.scrollLeft };
$thead.css($css);
$tfoot.css($css);
});
注意:提供的示例在IE中无法正确呈现,并且需要jQuery来提供水平滚动。无论如何我不关心水平滚动,所以如果解决方案不这样做就没问题。
答案 0 :(得分:16)
使用flexbox的解决方案尚未发布。
这是我使用display: flex
的解决方案以及:after
的基本用法(感谢Luggage),即使滚动条填充tbody
,也能保持对齐。这已在 Chrome 45,Firefox 39和MS Edge 中得到验证。可以使用前缀属性修改它以在IE11中工作,并在IE10中使用CSS hack和2012 flexbox syntax进行修改。
注意表格宽度可以修改;这甚至适用于100%
宽度。
唯一需要注意的是,所有表格单元格必须具有相同的宽度。下面是一个明确设计的例子,但是当单元格内容不同时(表格单元格具有相同的宽度和自动换行,强制flexbox保持相同的宽度,无论内容如何),这都可以正常工作。 Here是单元格内容不同的示例。
只需将.scroll
类应用于您想要滚动的表格,并确保它有thead
:
.scroll {
border: 0;
border-collapse: collapse;
}
.scroll tr {
display: flex;
}
.scroll td {
padding: 3px;
flex: 1 auto;
border: 1px solid #aaa;
width: 1px;
word-wrap: break;
}
.scroll thead tr:after {
content: '';
overflow-y: scroll;
visibility: hidden;
height: 0;
}
.scroll thead th {
flex: 1 auto;
display: block;
border: 1px solid #000;
}
.scroll tbody {
display: block;
width: 100%;
overflow-y: auto;
height: 200px;
}
<table class="scroll" width="400px">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
<td>Data</td>
</tr>
</table>
答案 1 :(得分:13)
此答案将用作不完全支持的position: sticky
的占位符,并将随着时间的推移而更新。目前建议不要在生产环境中使用此方法的本地实现。
有关当前支持,请参见:https://caniuse.com/#feat=css-sticky
position: sticky
一个替代答案是使用position: sticky
。 As described by W3C:
粘性放置的框的位置与相对放置的框的位置类似,但是偏移量是使用滚动框参照最近的祖先,如果没有祖先具有滚动框,则参照视口进行计算。
这恰好描述了相对静态标头的行为。将其分配给<thead>
或第一个<tr>
HTML标签很容易,因为应该支持according to W3C。但是,Chrome和IE and Edge都在为这些标签分配粘性位置属性时遇到问题。目前,解决这个问题似乎还没有优先考虑。
对于表格元素似乎起作用的是将sticky属性分配给表格单元。在这种情况下,<th>
个单元格。
由于表不是尊重您为其分配的静态大小的块元素,因此最好使用包装器元素来定义滚动溢出。
div {
display: inline-block;
height: 150px;
overflow: auto
}
table th {
position: -webkit-sticky;
position: sticky;
top: 0;
}
/* == Just general styling, not relevant :) == */
table {
border-collapse: collapse;
}
th {
background-color: #1976D2;
color: #fff;
}
th,
td {
padding: 1em .5em;
}
table tr {
color: #212121;
}
table tr:nth-child(odd) {
background-color: #BBDEFB;
}
<div>
<table border="0">
<thead>
<tr>
<th>head1</th>
<th>head2</th>
<th>head3</th>
<th>head4</th>
</tr>
</thead>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
<td>row 1, cell 2</td>
<td>row 1, cell 2</td>
</tr>
</table>
</div>
在此示例中,我使用一个简单的<div>
包装器来定义静态高度为150px
的滚动溢出。当然可以是任何大小。现在已经定义了滚动框,粘性<th>
元素将对应于“使用滚动框的最近祖先”,即div包装器。
position: sticky
polyfill 不受支持的设备可以使用polyfill,该polyfill通过代码实现行为。 stickybits是一个示例,它与浏览器实现的position: sticky
类似。
带有polyfill的示例:http://jsfiddle.net/7UZA4/6957/
答案 2 :(得分:8)
据我所知,没有标准的方法来实现这一点,只有CSS,虽然我认为应该有。 Mozilla浏览器过去常常用滚动体支持固定标题,但是在过去的几年里它们已经将它删除了。
在研究了一下之后,包括找到这个帖子,一位朋友刚刚为我开发了this solution;它使用Javascript但没有预制库,HTML标记的唯一要求是该表具有id名称。然后,在window.onload中,为每个表调用一个Javascript函数,给出id,height和width。如果在浏览器中禁用了Javascript,则会根据其原始标记显示整个表。如果启用了Javascript,则表格适合指定的高度和宽度,并且tbody会滚动,如果存在thead和tfoot,则它们将固定在顶部和底部。
答案 3 :(得分:7)
受@ Purag的回答启发,这是另一个flexbox解决方案:
/* basic settings */
table { display: flex; flex-direction: column; width: 200px; }
tr { display: flex; }
th:nth-child(1), td:nth-child(1) { flex-basis: 35%; }
th:nth-child(2), td:nth-child(2) { flex-basis: 65%; }
thead, tbody { overflow-y: scroll; }
tbody { height: 100px; }
/* color settings*/
table, th, td { border: 1px solid black; }
tr:nth-child(odd) { background: #EEE; }
tr:nth-child(even) { background: #AAA; }
thead tr:first-child { background: #333; }
th:first-child, td:first-child { background: rgba(200,200,0,0.7); }
th:last-child, td:last-child { background: rgba(255,200,0,0.7); }
&#13;
<table>
<thead>
<tr>
<th>a
<th>bbbb
<tbody>
<tr>
<td>fooo vsync dynamic
<td>bar
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
<tr>
<td>a
<td>b
</table>
&#13;
答案 4 :(得分:4)
我已经使用此代码轻松实现了这一目标:
所以你有这样的结构:
<table>
<thead><tr></tr></thead>
<tbody><tr></tr></tbody>
</table>
使用以下方式为thead设计样式:
<style>
thead{
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 0px;
}
</style>
需要考虑三件事:
首先,这个属性是新的。除了基于Webkit的浏览器的beta版本之外,它根本不受支持。请注意格式化。同样,如果您真的希望您的用户从粘性标头中受益,请使用javascript实现。
其次,如果您使用它,则需要合并供应商前缀。也许位置:粘性将在某一天起作用。但是现在,你需要使用position:-webkit-sticky(和其他人一样;在这篇文章中进一步检查css块)。
第三,目前没有任何定位默认值,所以你需要至少包括top:0;在与位置相同的css声明中:-webkit-sticky。否则,它只会在屏幕外滚动。
答案 5 :(得分:3)
如果您可以选择为表格单元格提供固定宽度(以及标题的固定高度),则可以使用position: fixed
选项:
http://jsfiddle.net/thundercracker/ZxPeh/23/
你只需要将它贴在iframe
中即可。你也可以通过给iframe
一个滚动条(我认为)来进行水平滚动。
编辑2015
如果您可以预先定义表格单元格的宽度(以百分比表示),那么这里有一些更优雅(仅限CSS)的解决方案:
答案 6 :(得分:3)
仅限CSS:
<强> CSS 强>:
tr {
width: 100%;
display: inline-table;
table-layout: fixed;
}
table{
height:300px; // <-- Select the height of the table
display: -moz-groupbox; // Firefox Bad Effect
}
tbody{
overflow-y: scroll;
height: 200px; // <-- Select the height of the body
width: 100%;
position: absolute;
}
Bootply :http://www.bootply.com/AgI8LpDugl
答案 7 :(得分:1)
我看到这个帖子已经暂停了一段时间,但是这个主题让我感兴趣,现在有了一些CSS3选择器,这变得更容易了(而且只用CSS非常可行)。
此解决方案依赖于具有表容器的最大高度。但只要您可以使用:first-child
选择器,它就会受到支持。
小提琴here。
如果有人能改进这个答案,请做!我计划很快在商业应用中使用这个解决方案!
<强> HTML 强>
<div id="con">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<强> CSS 强>
#con{
max-height:300px;
overflow-y:auto;
}
thead tr:first-child {
background-color:#00f;
color:#fff;
position:absolute;
}
tbody tr:first-child td{
padding-top:28px;
}
答案 8 :(得分:1)
我遇到了同样的问题,经过2天的研究后,我发现Ksesocss的解决方案适合我,也许对你也有好处。它允许固定的标题和动态宽度,只使用CSS。唯一的问题是源是西班牙语,但你可以在那里找到html和css代码。
这是链接:
http://ksesocss.blogspot.com/2014/10/responsive-table-encabezado-fijo-scroll.html
我希望这会有所帮助
答案 9 :(得分:1)
如果在所有提到的解决方案都不起作用的情况下(因为它适合我),请尝试使用两个解决方案,正如我在此回答中所解释的那样
答案 10 :(得分:0)
由于我最近需要这个,我将分享使用3个表的解决方案,但不需要JavaScript。
表1(父)包含两行。第一行包含列标题的表2(子1)。第二行包含滚动内容的表3(子2)。
必须注意,childTbl
必须比25px
短parentTbl
才能使滚动条正确显示。
This是来源,我从中得到了这个想法。我没有弃用的标签和内联CSS,使HTML5友好。
.parentTbl table {
border-spacing: 0;
border-collapse: collapse;
border: 0;
width: 690px;
}
.childTbl table {
border-spacing: 0;
border-collapse: collapse;
border: 1px solid #d7d7d7;
width: 665px;
}
.childTbl th,
.childTbl td {
border: 1px solid #d7d7d7;
}
.scrollData {
width: 690;
height: 150px;
overflow-x: hidden;
}
&#13;
<div class="parentTbl">
<table>
<tr>
<td>
<div class="childTbl">
<table class="childTbl">
<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>
</tr>
</table>
</div>
</td>
</tr>
<tr>
<td>
<div class="scrollData childTbl">
<table>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
<tr>
<td>Table Data 1</td>
<td>Table Data 2</td>
<td>Table Data 3</td>
<td>Table Data 4</td>
<td>Table Data 5</td>
<td>Table Data 6</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>
&#13;
这在不同的浏览器上是可靠的,缺点是必须对表格宽度进行硬编码。
答案 11 :(得分:0)
我最近试图弄清楚这一点,我想出了一个很好的解决方案,可以在我的浏览器中完美运行(Chrome 51),支持动态列宽。我应该提一下,在我独立地得出我的答案后,我也发现了一种在网络上其他地方描述的类似技术......
诀窍是使用两个相同的表位于彼此之上。下表是可见的,上表对于标题是不可见的。上表还在tbody上设置了pointer-events: none
,因此鼠标交互点击了下面的表格。这样,下表在上表的标题下滚动。
对于要正确布局和调整大小的所有内容(例如,当用户调整屏幕宽度时),两个表都需要具有相同的滚动条行为。但是,由于pointer-events: none
,上表的滚动条会被忽略,并且可以通过以下方式隐藏:
<style>
.hiddenScrollbar::-webkit-scrollbar {
background-color: transparent;
}
</style>
以下是完整的代码:
<html>
<head>
<style>
td {
border: 1px solid black;
white-space: nowrap;
}
th {
background-color: gray;
border: 1px solid black;
white-space: nowrap;
}
.hiddenScrollbar::-webkit-scrollbar {
background-color: transparent;
}
</style>
</head>
<body>
Table test. Use mouse wheel to scroll or scroll to the right to see vertical scroll bar. You can also remove the outermost div if you don't want a horizontal scroll bar.
<br/>
<div style="display: inline-block; height: 10em; width: 15em; overflow-x: scroll; overflow-y: hidden">
<div style="position: relative;">
<div style="display: inline-block; position: absolute; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
<table style="border-collapse: collapse;">
<thead>
<tr>
<th>Column 1</th>
<th>Another Column</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 2</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 3</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 4</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 5</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 6</td>
<td>12340921375021342354235 very long...</td>
</tr>
<tr>
<td>Data 7</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 8</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 9</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 10</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 11</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 12</td>
<td>123409213750213</td>
</tr>
</tbody>
</table>
</div>
<div class="hiddenScrollbar" style="display: inline-block; pointer-events: none; position: relative; left: 0px; top: 0px; height: 10em; overflow-y: scroll">
<table style="border-collapse: collapse;">
<thead style="pointer-events: auto">
<tr>
<th>Column 1</th>
<th>Another Column</th>
</tr>
</thead>
<tbody style="visibility: hidden">
<tr>
<tr>
<td>Data 1</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 2</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 3</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 4</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 5</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 6</td>
<td>12340921375021342354235 very long...</td>
</tr>
<tr>
<td>Data 7</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 8</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 9</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 10</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 11</td>
<td>123409213750213</td>
</tr>
<tr>
<td>Data 12</td>
<td>123409213750213</td>
</tr>
</tr>
</tbody>
</table>
</div>
</div>
</div><br/>
Stuff after table.
</body>
</html>
警告:需要做更多工作才能证明这在其他浏览器中有效。我在混合内联和样式表样式方面相当自由。但是我相信一般的概念是最好的方法,因为目标浏览器支持它。 唯一的功能/显示问题是,如果您需要水平滚动条,则垂直滚动条可以滚出视图(如代码段中所示)。您仍然可以使用鼠标滚轮滚动。 此外,您无法在标题上显示透明背景(否则下方表格会显示)。最后,您需要一种方法来生成两个相同的表。我个人使用react.js并且很容易做出反应,但php或其他服务器端生成或javascript也可以。
答案 12 :(得分:0)
另一个实现,但tbody
和动态列没有任何溢出。但需要JavaScript。容器div
用于容纳列标题。当表格滚过视口时,顶部会出现一个固定的标题。如果表格水平滚动,固定标题也会滚动。
使用带有span
的{{1}}元素创建列标题,并使用负边距水平滚动标题。还使用display: inline-block
优化以避免任何混乱。
RequestAnimationFrame