Table header 固定,可滚动 body 水平和垂直,可变单元格宽度
Table header fixed, scrollable body horizontal and vertical, variable cell width
我意识到这个问题在 Stack Overflow 上被问了很多;但是,在浏览了其中的一些之后,我相信我的问题还有一个要求。我想将常规 html table 转换为可以垂直和水平滚动的 table,而 header 是固定的。我项目中的table是动态生成的,所以单元格宽度无法固定
问题:
- 左右滚动时,table滚动,header被截断
- header 和 body 单元格宽度不适合
这是一个 JSFiddle 来向您展示我的问题
Table 示例:
<div class="table-responsive">
<table id="vehicleTable" class="table pointer hover table-striped table-bordered" role="grid">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
<th>Gender</th>
<th>Size</th>
<th>Mass</th>
<th>Eyecolor</th>
<th>Style</th>
<th>Shoe</th>
<th>Sport</th>
<th>Social Media</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Football</td>
<td>Facebook</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Golf</td>
<td>Facebook</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Golf</td>
<td>Facebook</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
</tbody>
</table>
</div>
CSS:
table#vehicleTable {
position: relative;
display: block;
margin-left: 0px;
width: 400px;
height: 400px;
table-layout: fixed;
}
table#vehicleTable thead {
position: relative;
display: block; /*seperates the header from the body allowing it to be positioned*/
width: inherit;
overflow-y: hidden;
overflow-x: hidden;
background-color: blue;
color: white;
}
table#vehicleTable tbody {
position: relative;
display: block; /*seperates the tbody from the header*/
width: inherit;
max-height: 400px;
height: 400px;
overflow-y: scroll;
overflow-x: scroll;
}
.table-responsive {
display: block;
height: 400px;
table-layout: fixed;
}
table#vehicleTable td, table#vehicleTable thead th {
table-layout: fixed;
}
JQuery:
$(document).ready(function () {
$('tbody').scroll(function (e) {
$('thead').css("left", -$("tbody").scrollLeft());
$('thead th div:nth-child(1)').css("left", $("tbody").scrollLeft());
$('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft());
});
});
编辑以处理更长列的可能性,因为我没有注意到先决条件
有趣的问题!
如果您乐于为列设置固定宽度,您可以用更少 CSS
和没有 jQuery
来实现您想要的效果:
如果您确保设置 CSS 以便默认列宽与任何 table header 所需的一样长,那么此解决方案应该有效:
CSS
table#vehicleTable {
position: relative;
display: block;
margin-left: 0px;
width: 400px;
height: 400px;
overflow-x: scroll;
overflow-y: hidden;
}
table#vehicleTable thead {
background-color: blue;
color: white;
}
table#vehicleTable tbody {
position: relative;
display: inline-block;
height: 345px; /*allowing for scrollbar and th height */
overflow-y: scroll;
}
table#vehicleTable td, table#vehicleTable th {
min-width: 100px; /*suitable width for all column headers in the example*/
}
/*Added this just to handle the 2nd column, which needs to be smaller, as per comments */
table#vehicleTable td:nth-of-type(2), table#vehicleTable th:nth-of-type(2) {
min-width: 30px;
text-align: center;
}
jQuery
$(window).on('load', function () {
$i = 0;
$("#vehicleTable tbody tr:first-of-type td").each(function()
{
$i++;
width = $(this).outerWidth();
$("#vehicleTable thead th:nth-of-type(" +$i+")").css({"min-width": width+"px"});
});
});
这将遍历 tbody
的第一个 row
,并获取每列的相应宽度。如果您不先在它们上设置 min-width
,那么任何包含比 header 列短的数据的列都会导致该列缩小,而 header 本身仍会扩展以适合自己的内容。
也更新了JSFiddle
我意识到这个问题在 Stack Overflow 上被问了很多;但是,在浏览了其中的一些之后,我相信我的问题还有一个要求。我想将常规 html table 转换为可以垂直和水平滚动的 table,而 header 是固定的。我项目中的table是动态生成的,所以单元格宽度无法固定
问题:
- 左右滚动时,table滚动,header被截断
- header 和 body 单元格宽度不适合
这是一个 JSFiddle 来向您展示我的问题
Table 示例:
<div class="table-responsive">
<table id="vehicleTable" class="table pointer hover table-striped table-bordered" role="grid">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
<th>Gender</th>
<th>Size</th>
<th>Mass</th>
<th>Eyecolor</th>
<th>Style</th>
<th>Shoe</th>
<th>Sport</th>
<th>Social Media</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Football</td>
<td>Facebook</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Golf</td>
<td>Facebook</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Golf</td>
<td>Facebook</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
<td>Female</td>
<td>1.60</td>
<td>60</td>
<td>Green</td>
<td>Cool</td>
<td>New Balance</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Anthony</td>
<td>Meyer</td>
<td>34</td>
<td>Male</td>
<td>1.84</td>
<td>88</td>
<td>Blue</td>
<td>Elegant</td>
<td>All stars</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
<td>Female</td>
<td>1.58</td>
<td>55</td>
<td>Green</td>
<td>Cool</td>
<td>Adidas</td>
<td>Chess</td>
<td>Instagram</td>
</tr>
</tbody>
</table>
</div>
CSS:
table#vehicleTable {
position: relative;
display: block;
margin-left: 0px;
width: 400px;
height: 400px;
table-layout: fixed;
}
table#vehicleTable thead {
position: relative;
display: block; /*seperates the header from the body allowing it to be positioned*/
width: inherit;
overflow-y: hidden;
overflow-x: hidden;
background-color: blue;
color: white;
}
table#vehicleTable tbody {
position: relative;
display: block; /*seperates the tbody from the header*/
width: inherit;
max-height: 400px;
height: 400px;
overflow-y: scroll;
overflow-x: scroll;
}
.table-responsive {
display: block;
height: 400px;
table-layout: fixed;
}
table#vehicleTable td, table#vehicleTable thead th {
table-layout: fixed;
}
JQuery:
$(document).ready(function () {
$('tbody').scroll(function (e) {
$('thead').css("left", -$("tbody").scrollLeft());
$('thead th div:nth-child(1)').css("left", $("tbody").scrollLeft());
$('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft());
});
});
编辑以处理更长列的可能性,因为我没有注意到先决条件
有趣的问题!
如果您乐于为列设置固定宽度,您可以用更少 CSS
和没有 jQuery
来实现您想要的效果:
如果您确保设置 CSS 以便默认列宽与任何 table header 所需的一样长,那么此解决方案应该有效:
CSS
table#vehicleTable {
position: relative;
display: block;
margin-left: 0px;
width: 400px;
height: 400px;
overflow-x: scroll;
overflow-y: hidden;
}
table#vehicleTable thead {
background-color: blue;
color: white;
}
table#vehicleTable tbody {
position: relative;
display: inline-block;
height: 345px; /*allowing for scrollbar and th height */
overflow-y: scroll;
}
table#vehicleTable td, table#vehicleTable th {
min-width: 100px; /*suitable width for all column headers in the example*/
}
/*Added this just to handle the 2nd column, which needs to be smaller, as per comments */
table#vehicleTable td:nth-of-type(2), table#vehicleTable th:nth-of-type(2) {
min-width: 30px;
text-align: center;
}
jQuery
$(window).on('load', function () {
$i = 0;
$("#vehicleTable tbody tr:first-of-type td").each(function()
{
$i++;
width = $(this).outerWidth();
$("#vehicleTable thead th:nth-of-type(" +$i+")").css({"min-width": width+"px"});
});
});
这将遍历 tbody
的第一个 row
,并获取每列的相应宽度。如果您不先在它们上设置 min-width
,那么任何包含比 header 列短的数据的列都会导致该列缩小,而 header 本身仍会扩展以适合自己的内容。
也更新了JSFiddle