简体   繁体   English

修复了标题和可滚动的主体

[英]Fixed header and scrollable body

I have like 15 columns in the table. 我在表格中有15列。 I want to scroll both horizontal and vertical and header should be fixed when I scroll vertical. 我想滚动水平和垂直,当我滚动垂直时,标题应该是固定的。 I have tried various examples but no luck. 我尝试过各种各样的例子,但没有运气。 All I see header columns are not aligning with data. 我看到的所有标题列都没有与数据对齐。 Column width are not fixed as number of columns vary based on the user selection 列宽度不固定,因为列数根据用户选择而变化

Please guide me to the correct example. 请引导我到正确的例子。

It's easily acheived with css. 它很容易用css实现。 It all comes down to the following: 这一切都归结为以下几点:

table {
    overflow-x:scroll;
}

tbody {
    max-height: /*your desired max height*/
    overflow-y:scroll;
    display:block;
}

Updated for IE9 JSFiddle example 更新了IE9 JSFiddle示例

what you could do is a bit of visual trick to achieve this, use two div tags 你可以做的是实现这一点的一些视觉技巧,使用两个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>

now with a bit of JavaScript or JQuery you can get the th, set its width to match the cell width, and move the th cell to the "Headers" table 现在使用一些JavaScript或JQuery,您可以得到th,设置其宽度以匹配单元格宽度,并将第三个单元格移动到“Headers”表

$(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++;
    });
});

now only is left to do is to style the div "Table" with overflow, so now if you would scroll the second table the header will remain in place, i used jquery to simplify the readability, but can be done in JavaScript is same way 现在唯一要做的就是用溢出来设置div“Table”的样式,所以现在如果要滚动第二个表,标题将保持原位,我使用jquery来简化可读性,但是可以用JavaScript完成同样的方式

Live Demo 现场演示

Example with automatic vertical scroll body and header 自动垂直滚动体和标题的示例

I have created a pure CSS solution to this problem that may work better for some people than the accepted answer (which I can't seem to get working at all). 我已经为这个问题创建了一个纯CSS解决方案,对于某些人而言可能比接受的答案更好(我似乎根本无法工作)。 Unlike most of the other scrolling-body tables I've seen that don't require fixed widths, mine has a minimum width that is determined by its content. 与我见过的大多数其他滚动体表不同,不需要固定宽度,我的最小宽度由其内容决定。 It will wrap text if possible to avoid overflowing its container (except in the headers, which don't allow soft-wrapping, unfortunately), but once the wrapping opportunities are used up, it won't get any narrower. 如果可能的话,它将包装文本以避免溢出其容器(不幸的是,在标题中,不允许软包装),但是一旦包装机会用完,它就不会变得更窄。 That forces the parent element (usually the body tag) to handle the horizontal scrolling, which keeps the headers and columns in sync. 这会强制父元素(通常是body标签)处理水平滚动,从而使标题和列保持同步。

Here's a fiddle . 这是一个小提琴

Here's the code: 这是代码:

HTML 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 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*/

And here's a post where I answered in a little more detail. 这是一篇帖子 ,我在后面详细回答。

你应该使用一些第三方表,如YUI表

Here is a pure javascript solution using TableAdjuster and TableData classes: 这是一个使用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> 

I have found a system that is 我找到了一个系统

  • Compatible with Internet Explorer 9 + Chrome + Firefox (Windows) and Safari (Mac) 兼容Internet Explorer 9 + Chrome + Firefox(Windows)和Safari(Mac)
  • Without using javascript 不使用javascript
  • Using only une div and one table 仅使用une div和一个表
  • Fixed header and footer (EXCEPT for IE), with scrollable body. 修复了页眉和页脚(IE的例外情况),带有可滚动的正文。 Header and body with same column widths 具有相同列宽的标题和正文

Result: 结果: 在此输入图像描述

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM