为了使<tbody>元素可滚动,我们需要改变它在页面上的显示方式,即使用display: block;将其显示为块级元素。
既然我们改变了tbody的显示属性,我们也应该改变thead元素的显示属性,以防止破坏表格布局。
所以我们有:
thead, tbody { display: block; }
tbody {
height: 100px; /* Just for the demo */
overflow-y: auto; /* Trigger vertical scroll */
overflow-x: hidden; /* Hide the horizontal scroll */
}
Web浏览器默认将header和tbody元素显示为row-group (table-header-group和table-row-group)。
一旦我们改变了它,里面的tr元素就不会填满它们容器的整个空间。
为了解决这个问题,我们必须计算tbody列的宽度,并通过JavaScript将相应的值应用到标题列。
自动宽度列
下面是上述逻辑的jQuery版本:
// Change the selector if needed
var $table = $('table'),
$bodyCells = $table.find('tbody tr:first').children(),
colWidth;
// Get the tbody columns width array
colWidth = $bodyCells.map(function() {
return $(this).width();
}).get();
// Set the width of thead columns
$table.find('thead tr').children().each(function(i, v) {
$(v).width(colWidth[i]);
});
下面是输出(在Windows 7 Chrome 32上):
工作演示。
全宽表,相对宽度列
根据原始海报的需要,我们可以将表格扩展到其容器宽度的100%,然后对表格的每列使用相对(百分比)宽度。
table {
width: 100%; /* Optional */
}
tbody td, thead th {
width: 20%; /* Optional */
}
由于表格具有(某种)流体布局,因此当容器调整大小时,我们应该调整标题列的宽度。
因此,一旦窗口调整大小,我们应该设置列的宽度:
// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
/* Same as before */
}).resize(); // Trigger the resize handler once the script runs
输出将是:
工作演示。
浏览器支持和替代方案
我在Windows 7上通过主流浏览器的新版本(包括IE10+)测试了上述两种方法,它们都有效。
但是,它在IE9及以下版本上不能正常工作。
这是因为在表格布局中,所有元素都应该遵循相同的结构属性。
通过使用display: block;对于<thead>和<tbody>元素,我们破坏了表的结构。
通过JavaScript重新设计布局
一种方法是重新设计(整个)表布局。使用JavaScript动态创建新布局,动态处理和/或调整单元格的宽度/高度。
例如,看看下面的例子:
jQuery .floatThead()插件(浮动/锁定/粘滞表头插件)
jQuery可滚动表插件。(源代码在github)
jQuery .FixedHeaderTable()插件(源代码在github)
数据表垂直滚动的例子。
嵌套表
这种方法使用两个包含div的嵌套表。第一个表只有一个包含div的单元格,而第二个表被放置在div元素中。
在CSS Play中检查垂直滚动表。
这适用于大多数浏览器。我们还可以通过JavaScript动态地执行上述逻辑。
在滚动上具有固定标题的表
由于向<tbody>添加垂直滚动条的目的是在每行的顶部显示表头,因此我们可以将thead元素定位为固定在屏幕的顶部。
下面是Julien对这种方法的工作演示。
它有一个很有前途的网络浏览器支持。
这里是Willem Van Bockstal的纯CSS实现。
纯CSS解决方案
这是老答案。当然,我已经添加了一个新方法并改进了CSS声明。
固定宽度的表格
在这种情况下,表应该有一个固定的宽度(包括列的宽度和垂直滚动条的宽度)。
每一列都应该有一个特定的宽度,头元素的最后一列需要一个更大的宽度,它等于其他的宽度+垂直滚动条的宽度。
因此,CSS将是:
table {
width: 716px; /* 140px * 5 column + 16px scrollbar width */
border-spacing: 0;
}
tbody, thead tr { display: block; }
tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
tbody td, thead th {
width: 140px;
}
thead th:last-child {
width: 156px; /* 140px + 16px scrollbar width */
}
输出如下:
工作演示。
100%宽度的表格
在这种方法中,表的宽度为100%,对于每个th和td, width属性的值应该小于100% / cols的个数。
同样,我们需要减少头部的宽度作为垂直滚动条宽度的值。
为了做到这一点,我们需要使用CSS3 calc()函数,如下所示:
table {
width: 100%;
border-spacing: 0;
}
thead, tbody, tr, th, td { display: block; }
thead tr {
/* fallback */
width: 97%;
/* minus scroll bar width */
width: -webkit-calc(100% - 16px);
width: -moz-calc(100% - 16px);
width: calc(100% - 16px);
}
tr:after { /* clearing float */
content: ' ';
display: block;
visibility: hidden;
clear: both;
}
tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
tbody td, thead th {
width: 19%; /* 19% is less than (100% / 5 cols) = 20% */
float: left;
}
这里是在线演示。
注意:如果每一列的内容都换行了,这种方法就会失败,即每个单元格的内容应该足够短。
下面是我在回答这个问题时创建的两个纯CSS解决方案的简单示例。
下面是jsFiddle演示v2。
旧版本:jsFiddle Demo v1