带固定标题的可滚动表

我有一个解决方案,我可以创建可滚动的表 w/固定的页眉/页脚使用小 jQuery 和 CSS-但我正在寻找一种方法,使之成为一个跨浏览器兼容的 CSS-only 解决方案。

明确地说,我正在寻求做的是使用 只有一个 table标签(它的有效子标签,colgroupcoltheadtbodytfoottrthtd) ,但采用一套 CSS 规则,将满足以下条件:

  1. 必须保持页眉/页脚/内容行之间的列对齐
  2. 当内容垂直滚动时,必须允许页眉/页脚保持固定
  3. 为了提供功能,必须不需要任何 jQuery 或其他 JavaScript
  4. 只能使用上面提供的标签

这个代码示例: 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 提供水平滚动。无论如何,我不关心水平滚动,所以如果一个解决方案不这样做也没关系。

185462 次浏览

如果可以选择为表单元格提供固定宽度(为标题提供固定高度) ,那么可以使用 position: fixed选项:

Http://jsfiddle.net/thundercracker/zxpeh/23/

你只需要把它插入 iframe。你也可以通过给 iframe一个滚动条来实现水平滚动(我认为)。


编辑2015

如果你可以预先定义表格单元格的宽度(按百分比) ,那么这里有一个更优雅的(仅 CSS)解决方案:

Http://jsfiddle.net/7ubmd/77/

据我所知,没有标准的方法来实现这一点只有 CSS,虽然我认为应该有。Mozilla 浏览器曾经支持带有滚动体的固定头文件,但是在过去几年中已经删除了。

经过一番研究,包括找到这篇文章,我的一个朋友刚刚为我开发了 这个解决方案; 它使用 Javascript,但没有固定的库,而且 HTML 标记的唯一要求是表有一个 id 名称。然后,在 window.onload 上,为给出 id、 height 和 width 的每个表调用一个 Javascript 函数。如果在浏览器中禁用了 Javascript,那么整个表将根据其原始标记显示。如果启用了 Javascript,那么表就可以放入指定的高度和宽度,并且 tbody 可以滚动,如果 head 和 tfoot 存在,那么它们就固定在顶部和底部。

我看到这个线程已经有一段时间没有活动了,但是这个主题引起了我的兴趣,现在有了一些 CSS3选择器,这就变得更容易了(而且只需要 CSS 就可以很好地实现)。

此解决方案依赖于表容器的最大高度。但是只要您可以使用 :first-child选择器,就支持它。

小提琴 给你

如果任何人可以改进这个答案,请做! 我计划使用这个解决方案在一个商业应用程序很快!

超文本标示语言

<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;
}

因为我最近需要这个,我将共享一个解决方案,使用3个表,但不需要 JavaScript。

表1(父表)包含两行。第一行包含列标题的表2(子1)。第二行包含用于滚动内容的表3(子2)。

必须指出的是,childTbl必须是 25px短于 parentTbl的滚动条出现正确。

这就是我灵感的来源。我使它对 HTML5友好,没有废弃的标签和内联 CSS。

.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;
}
<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>

这在不同的浏览器上是可靠的,缺点是必须硬编码表的宽度。

我也遇到过同样的问题,在花了两天时间研究后,我找到了这个来自 Ksesocss 的解决方案,它适合我,也许对你也有好处。它允许固定的标题和动态宽度,只使用 CSS。唯一的问题是源代码是西班牙语的,但是您可以在那里找到 html 和 css 代码。

这是链接:

Http://ksesocss.blogspot.com/2014/10/responsive-table-encabezado-fijo-scroll.html

希望这个能帮上忙

令人惊讶的解决方案使用弹性框尚未发布。

下面是我的解决方案,使用 display: flex:after的基本用法(感谢 行李)来维持对齐,即使滚动条填充 tbody一点点。这已在 Chrome 45,Firefox 39和 MS Edge中得到验证。它可以用前缀属性进行修改,以便在 IE11中工作,在 IE10中进一步使用 CSS 入侵2012年的 Flexbox 语法

注意,可以修改表的宽度; 这甚至适用于 100%宽度。

唯一需要注意的是,所有表单元格必须具有相同的宽度。下面是一个明显人为设计的示例,但是当单元格内容不同时(表格单元格都有相同的宽度和单词包装,迫使 flebox 不管内容如何都保持相同的宽度) ,这种方法都可以很好地工作。给你是单元格内容不同的一个示例。

只需将 .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-word;
}


.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>

最近我自己也在尝试解决这个问题,我想出了一个很好的解决方案,可以在我的浏览器(Chrome51)和 支持动态列宽中完美运行。我应该提到的是,在我独立得出我的答案之后,我还发现了网上其他地方描述的一种类似的技术..。

诀窍是使用两个位于彼此之上的完全相同的表。下表是可见的,上表是不可见的,除了头部。上面的表格也在主体上设置了 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,使用 response 很容易,但是 PHP 或其他服务器端生成或 javascript 也可以工作。

另一个实现,但在 tbody和动态列上没有任何溢出。但是需要使用 JavaScript。容器 div用于容纳列标题。当表滚动过视图端口时,顶部会显示一个固定的标题。如果表是水平滚动的,那么固定的页眉也会水平滚动。

使用带有 display: inline-blockspan元素创建列标题,并使用负边距水平滚动标题。还使用 RequestAnimationFrame进行了优化,以避免任何混乱。

function rAF(scrollLeft) {
var offsetLeft = 0 - scrollLeft;
$('.hdr__inner span:first-child').css('margin-left', offsetLeft);
}

Https://codepen.io/lloydleo/pen/nrpqee

受到@Purag 回答的启发,这里有另一个灵活的解决方案:

/* 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); }
<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>

只有 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.com/AgI8LpDugl”rel = “ nofollow noReferrer”> http://www.Bootply.com/agi8lpdugl

我很容易就做到了这一点,使用这个代码:

所以你有这样一个结构:

<table>
<thead><tr></tr></thead>
<tbody><tr></tr></tbody>
</table>

只要把头部的样式设计成:

<style>
thead{
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 0px;
}
</style>

有三件事需要考虑:

首先,此属性是新的。除了基于 Webkit 的浏览器的 beta 版本之外,它根本不受支持。所以请注意。同样,如果您真的希望您的用户从粘贴头中获益,那么使用 javascript 实现。

其次,如果使用它,则需要合并供应商前缀。也许位置: 粘性总有一天会起作用。但是现在,您需要使用 position:-webkit-stick (以及其他内容; 请查看本文后面的 css 代码块)。

第三,目前没有任何定位默认值,因此您至少需要在同一个 css 声明中包含 top: 0; 作为 position:-webkit-stick。否则,它就会滚出屏幕。

如果所有提到的解决方案都不起作用(对我来说就是这样) ,那么就尝试一个双表解决方案,就像我在这个答案中解释的那样

Https://stackoverflow.com/a/47722456/6488361

这个答案将用作不完全支持的 position: sticky的占位符,并随着时间的推移而更新。当前建议不要在生产环境中使用这种方法的本地实现。

请参阅目前的支持: https://caniuse.com/#feat=css-sticky


使用 position: sticky

另一种解决办法是使用 position: sticky:

粘性定位框的位置与相对定位框的位置相似,但是偏移量是参照最近的具有滚动框的祖先计算的,或者如果没有祖先具有滚动框,则参照视窗计算的。

这正好描述了相对静态头的行为。很容易将其分配给 <thead>或第一个 <tr> HTML-tag,因为应该支持 根据 W3C。但是,铬合金IE 和 Edge都存在为这些标记分配粘贴位置属性的问题。目前似乎也没有优先解决这个问题。

对于 table 元素来说,似乎可行的方法是将粘性属性分配给 table-cell。在这种情况下,<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,它通过代码实现行为。一个例子是 黏糊糊的东西,它类似于浏览器实现的 position: sticky的相同行为。

使用 polyfill 的示例: < a href = “ http://jsfiddle.net/7UZA4/6957/”rel = “ norefrer”> http://jsfiddle.net/7uza4/6957/