我在表中有 15 列。我想水平和垂直滚动,当我垂直滚动时,标题应该是固定的。我尝试了各种示例,但没有运气。我看到的所有标题列都没有与数据对齐。列宽不固定,因为列数因用户选择而异
请引导我到正确的例子。
我在表中有 15 列。我想水平和垂直滚动,当我垂直滚动时,标题应该是固定的。我尝试了各种示例,但没有运气。我看到的所有标题列都没有与数据对齐。列宽不固定,因为列数因用户选择而异
请引导我到正确的例子。
用css很容易实现。这一切都归结为以下几点:
table {
overflow-x:scroll;
}
tbody {
max-height: /*your desired max height*/
overflow-y:scroll;
display:block;
}
更新了 IE9 JSFiddle 示例
你可以做的是一些视觉技巧来实现这一点,使用两个 div 标签
<div class="Headers">
<table class="NewHeader">
<tr>
</tr>
</table>
</div>
<div class="Table">
<table class="MyTable">
<tr>
<th>
</th>
...
</tr>
<tr>
<td>
</td>
...
</tr>
</div>
现在使用一点 JavaScript 或 JQuery,您可以获得 th,将其宽度设置为与单元格宽度匹配,然后将 th 单元格移动到“标题”表
$(document).ready(function(){
var counter = 0;
$(".MyTable th").each(function(){
var width = $('.MyTable tr:last td:eq(' + counter + ')').width();
$(".NewHeader tr").append(this);
this.width = width;
counter++;
});
});
现在唯一要做的就是用溢出设置 div“表”的样式,所以现在如果你滚动第二个表,标题将保持在原位,我使用 jquery 来简化可读性,但可以在 JavaScript 中以相同的方式完成
我为这个问题创建了一个纯 CSS 解决方案,对于某些人来说可能比公认的答案更好(我似乎根本无法工作)。与我见过的大多数不需要固定宽度的其他滚动体表不同,我的最小宽度由其内容决定。如果可能的话,它将包装文本以避免溢出其容器(在标题中除外,它不允许软包装,不幸的是),但是一旦包装机会用完,它就不会变得更窄。这会强制父元素(通常是 body 标签)处理水平滚动,从而使标题和列保持同步。
这是一个小提琴。
这是代码:
HTML
<div class="scrollingtable">
<div>
<div>
<table>
<caption>Top Caption</caption>
<thead>
<tr>
<th><div label="Column 1"/></th>
<th><div label="Column 2"/></th>
<th><div label="Column 3"/></th>
<th>
<!--more versatile way of doing column label; requires 2 identical copies of label-->
<div><div>Column 4</div><div>Column 4</div></div>
</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>
</div>
Faux bottom caption
</div>
</div>
CSS
<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
<style>
/*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;
}
.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*/
这是一篇我更详细地回答的帖子。
您应该使用一些第三方表,例如YUI 表
这是一个使用 TableAdjuster 和 TableData 类的纯 JavaScript 解决方案:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title></title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
.hdrDiv
{
width: 100%;
overflow-x: hidden;
}
.tblDiv
{
overflow-y: auto;
overflow-x: hidden;
margin: 0;
padding: 0;
height: 500px;
}
.hdr
{
width: 100%;
}
.hdr td, .tbl td
{
padding-left: 8px;
padding-right: 8px;
vertical-align: middle;
border-style: solid;
border-width: 1px;
border-color: rgb(163,163,163);
text-align: left;
cursor: default;
margin: 0;
}
.hdr td
{
font: bold 12px Tahoma;
padding-top: 4px;
padding-bottom: 4px;
}
.hdr td.col1
{
width: 20%;
}
.hdr td.col2
{
width: 20%;
}
.hdr td.col3
{
width: 25%;
}
.hdr td.col4
{
width: 35%;
}
.hdr, .tbl
{
table-layout: fixed;
min-width: 400px;
}
.tbl td
{
font: 12px Tahoma;
}
</style>
<script type="text/javascript">
var g_adjuster = null;
var g_initRowCount = 4;
function getScrollbarWidth()
{
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
outer.style.overflow = "scroll";
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
}
function ExtractInt(value)
{
var regExp = /([a-zA-Z])/g;
value = value.replace(regExp, "");
return (value.length == 0) ? 0 : parseInt(value);
}
function TableData(hdrID, tableID)
{
this.m_hdrID = hdrID;
this.m_tableID = tableID;
this.m_pbWidth = 0;
var header = document.getElementById(this.m_hdrID);
var table = document.getElementById(this.m_tableID);
this.m_hasSB = table ? (table.parentNode.scrollHeight > table.parentNode.clientHeight) : false;
var hdrRow = (header != null && header.rows.length > 0) ? header.rows[0] : null;
var clsName = !hdrRow ? "" : (hdrRow.className.length > 0) ? hdrRow.className : (header.className.length > 0) ? header.className + " td" : "";
var elements = [];
elements.push({ prop: 'padding-left', value: ''});
elements.push({ prop: 'padding-right', value: ''});
elements.push({ prop: 'border-width', value: ''});
this.GetCSSValues('.' + clsName, elements);
for (var i=0; i<elements.length; i++)
{
var w = ExtractInt(elements[i].value);
if (elements[i].prop == 'border-width')
w *= 2;
this.m_pbWidth += w;
}
}
TableData.prototype.GetCSSValues =
function(theClass, elements)
{
var classLower = theClass.toLowerCase();
var cssRules;
for (var i = 0; i < document.styleSheets.length; i++)
{
var found = true;
try
{
if (document.styleSheets[i]['rules'])
cssRules = 'rules';
else if (document.styleSheets[i]['cssRules'])
cssRules = 'cssRules';
else
{
found = false;
}
}
catch(err)
{
break;
}
if (!found)
continue;
for (var j = 0; j < document.styleSheets[i][cssRules].length; j++)
{
if (typeof document.styleSheets[i][cssRules][j].selectorText != 'string')
continue;
var selectorLower = document.styleSheets[i][cssRules][j].selectorText.toLowerCase();
if (selectorLower.indexOf(classLower) >= 0)
{
for (var k=0; k<elements.length; k++)
{
var v = document.styleSheets[i][cssRules][j].style.getPropertyValue(elements[k].prop);
if (typeof v == 'string' && v.length > 0)
elements[k].value = v;
}
}
}
}
}
TableData.prototype.Adjust =
function(sbWidth)
{
var header = document.getElementById(this.m_hdrID);
var table = document.getElementById(this.m_tableID);
var hdrRow = (header != null && header.rows.length > 0) ? header.rows[0] : null;
if (!hdrRow || !table)
return;
var hasSB = table.parentNode.scrollHeight > table.parentNode.clientHeight;
header.style.width = hasSB ? "calc(100% - " + sbWidth.toString() + "px)" : "100%";
var colCount = hdrRow.cells.length;
for (var i=0; i<table.rows.length; i++)
{
var r = table.rows[i];
for (var j=0; j<r.cells.length; j++)
{
if (j >= colCount)
break;
var w = hdrRow.cells[j].offsetWidth - this.m_pbWidth;
r.cells[j].style.width = w + 'px';
}
}
}
function TableAdjuster()
{
this.m_sbWidth = getScrollbarWidth();
this.m_data = [];
}
TableAdjuster.prototype.AddTable =
function(hdrID, tableID)
{
// We can have multiple scrollable tables on the page
this.m_data.push(new TableData(hdrID, tableID));
}
TableAdjuster.prototype.Adjust =
function()
{
for (var i=0; i<this.m_data.length; i++)
this.m_data[i].Adjust(this.m_sbWidth);
}
function DeleteRow()
{
var table = document.getElementById("tablebody");
if (table != null && table.rows.length > 0)
table.deleteRow(table.rows.length-1);
AdjustSize();
}
function AddRow(adjust)
{
var header = document.getElementById("header");
var table = document.getElementById("tablebody");
var hdrRow = (header != null && header.rows.length > 0) ? header.rows[0] : null;
if (!hdrRow || !table)
return;
var colCount = hdrRow.cells.length;
var rowNum = table.rows.length + 1;
var r = table.insertRow(-1);
for (var i=0; i<colCount; i++)
{
var c = r.insertCell(-1);
c.innerHTML = "Row " + rowNum.toString() + " Column " + (i + 1).toString() + " content";
}
if (adjust)
AdjustSize();
}
function AdjustSize()
{
g_adjuster.Adjust();
}
function InitPage()
{
for (var i=0; i<g_initRowCount; i++)
AddRow(false);
g_adjuster = new TableAdjuster();
g_adjuster.AddTable("header", "tablebody");
AdjustSize();
}
</script>
</head>
<body onload="InitPage()" onresize="AdjustSize()">
<div id="headerDiv" class="hdrDiv">
<table id="header" class="hdr">
<tr>
<td class="col1">Column 1 Title</td>
<td class="col2">Column 2 Title</td>
<td class="col3">Column 3 Title</td>
<td class="col4">Column 4 Title</td>
</tr>
</table>
</div>
<div id="tableDiv" class="tblDiv">
<table id="tablebody" class="tbl">
</table>
</div>
<div style="margin-top: 12px">
<input id="Button1" type="button" value="Add Row" onclick="AddRow(true);"/>
<input id="Button2" type="button" value="Delete Row" onclick="DeleteRow();"/>
</div>
</body>
</html>
我找到了一个系统
结果:
HTML:
<thead>
<tr>
<th class="nombre"><%= f.label :cost_center %></th>
<th class="cabecera cc">Personal</th>
<th class="cabecera cc">Dpto</th>
</tr>
</thead>
<tbody>
<% @cost_centers.each do |cc| %>
<tr>
<td class="nombre"><%= cc.nombre_corto %></td>
<td class="cc"><%= cc.cacentrocoste %></td>
<td class="cc"><%= cc.cacentrocoste_dpto %></td>
</tr>
<% end %>
</tbody>
<tfoot>
<tr>
<td colspan="3"><a href="#">Mostrar mas usuarios</a></td>
</tr>
</tfoot>
</table>
CSS:
div.cost_center{
font-size:75%;
margin-left:5px;
margin-top:5px;
margin-bottom: 2px;
float: right;
display: inline-block;
overflow-y: auto;
overflow-x: hidden;
max-height:300px;
}
div.cost_center label {
float:none;
font-size:14px;
}
div.cost_center table{
width:300px;
border-collapse: collapse;
float:right;
table-layout:fixed;
}
div.cost_center table tr{
height:16px;
}
div.cost_center th{
font-weight:normal;
}
div.cost_center table tbody{
display: block;
overflow: auto;
max-height:240px;
}
div.cost_center table thead{
display:block;
}
div.cost_center table tfoot{
display:block;
}
div.cost_center table tfoot td{
width:280px;
}
div.cost_center .cc{
width:60px;
text-align: center;
border: 1px solid #999;
}
div.cost_center .nombre{
width:150px;
}
div.cost_center tbody .nombre{
border: 1px solid #999;
}
div.cost_center table tfoot td{
text-align:center;
border: 1px solid #999;
}
div.cost_center table th,
div.cost_center table td {
padding: 2px;
vertical-align: middle;
}
div.cost_center table tbody td {
white-space: normal;
font: .8em/1.4em Verdana, sans-serif;
color: #000;
background-color: white;
}
div.cost_center table th.cabecera {
font: 0.8em/1.4em Verdana, sans-serif;
color: #000;
background-color: #FFEAB5;
}