在可滚动的div中固定表头

9

我有三个div,分别是Header、Central和Footer。在Central div中有一个表格(gridview),它几乎总是比外部div更长。因此,我已经使这个div在垂直方向上可以滚动。问题是:如何使表头在div向下滚动后仍然可见?我可以使用单独的div或表格来创建表头并使其固定,但表格中列的宽度并不总是相同的 - 因此我不知道如何维护表头中列的宽度。有什么线索吗?

11个回答

13

我刚刚编写了一个jQuery插件,可以完全满足你的需求。它非常小巧且易于实现。

只需要一个包含thead和tbody的表格即可。

您可以将该表格放入具有类名的DIV中,表格将始终调整大小以适应该DIV。例如,如果您的div随浏览器窗口缩放,则表格也会随之缩放。当滚动时,标题将固定在顶部。如果启用页脚,则页脚也将固定。您还可以选项克隆页眉并将其固定在页脚上。如果您使浏览器窗口过小而所有列无法适合...它也会水平滚动(页眉也是如此)。

只需将DIV的类名称传递给插件即可,例如:$('.myDiv').fixedHeaderTable({footer: true, footerId: 'myFooterId'}); 然后插件将完成其余工作。 FooterID是页面上包含页脚标记的元素。如果您想要将分页作为页脚,则使用此选项。

如果页面上有多个表格,它也适用于每个带有固定标题的表格。

请访问此处进行查看:http://fixedheadertable.mmalek.com/

请记住,它仍处于“beta”状态,因此我每天都会添加新功能和修复错误。

支持的浏览器:IE6、IE7、IE8、FireFox、Safari和Chrome。


当表格非常长时,加载需要更多时间(或导致浏览器崩溃)。我尝试了90 * 52行和列。 - ManiMuthuPandi

12
解决方案非常简单。你需要三个DIV:一个通用容器(我这里使用的是类名为"outer")、一个表格容器(我这里使用的是类名为"inner")以及一个DIV,其中使用jQuery或JavaScript对现有表格进行克隆(我这里使用的是类名为"header")。
解决方案使用了CSS和几行jQuery代码,将"inner"中的HTML克隆到"header"中并设置其宽度和高度。支持固定和可变列宽。在IE8、Firefox 9、Safari和Google Chrome上进行了测试。
以下是示例代码:

     $(document).ready(function() {
      $('.header').html( $('.inner').html() );
      $('.header').css('width', $('.inner table').outerWidth() );
      $('.header').css('height', $('.inner table thead').outerHeight() );
     });
table {
  width:100%;
}
th {
  border-top:1px solid #999;
  text-align:left;
}
td, th {
  border-bottom:1px solid #999;
  background-color:#EEE;
}
.outer {
  position:relative;
  width:500px;
}
.inner {
  height:150px;
  overflow:auto;
}
.header {
  position:absolute;
  top:0;
  left:0;
  overflow:hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="outer">
  <div class="inner">
    <table cellspacing="0" cellpadding="0">
      <thead>
        <tr>
          <th>a</th>
          <th>b</th>
          <th>c</th>
          <th>d</th>
        </tr>
      </thead>
      <tbody>
        <tr><td>1</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>2</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>3</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>4</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>5</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>6</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>7</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>8</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>9</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>10</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>11</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>12</td><td>b</td><td>c</td><td>d</td></tr>
      </tbody>
    </table>
  </div>

  <div class="header">
  </div>

</div>
</body>


11

这里有一个使用JavaScript的基本解决方案:

function position(table) {
    table.rows[0].style.position="absolute";
    table.rows[0].style.top="0px";
    table.style.marginTop = table.rows[0].clientHeight/1.2;
    var widths = Array();
    for(var i = 0; i < table.rows[0].cells.length; i++) {
        widths[i] = max(table.rows[0].cells[i].clientWidth, table.rows[1].cells[i].clientWidth);
    }
    for(var row = 0; row < table.rows.length; row++) {
        for(var col = 0; col < widths.length; col ++) {
            table.rows[row].cells[col].style.width = widths[col] + "px";
        }
    }
}

function max(num1, num2) { return (num1 > num2) ? num1 : num2; }

链接的示例已经不存在了。 我在尝试这个时遇到了麻烦,于是采用了下面提到的“愚蠢的固定标题”解决方案。 - LeBleu
2
我不会投票这个。它只是将每一行固定在页面顶部,而不适用于页面上除了这个表格之外还有其他内容的情况。 - Hemant Tank
请查看http://meetselva.github.io/fixed-table-rows-cols/,这是https://dev59.com/FHVC5IYBdhLWcg3wbglT的被接受答案。 - Steve Jansen

3
您需要将标题放在可滚动的div之外。div内的所有内容都会滚动。
编辑:关于宽度,如果您选择单独的标题,我可以提供几个解决方案:
- 假设这是动态内容,请根据字符串长度生成“固定”的宽度。显然,以EM为单位指定并留出一些误差余地。 - 使用JavaScript。 - 使用固定宽度列。
我实际上还没有尝试过第一个方法,这可能会使事情变得有些复杂。但如果您非常需要这种效果,可以尝试一下。我还应该提到,可能有使用表格组件的JavaScript库已经实现了这一点。查看它们以了解它们是如何做到的。

你是对的,但每个标题列的宽度怎么样?列的宽度不固定,取决于数据,会发生变化。因此,在标题单独的情况下如何保持它? - rafek

2
你可以尝试使用 jQuery 插件 Stupid Fixed Header。这项技术基本相同:复制一个表头并将其放置在表格层的顶部。

你有脚本的URL吗?链接似乎只能强制保存HTML文件。 - scunliffe

2

您需要在数据表格中使用标题来描述每一列。通过table-layout:fixed可以保持列宽的一致性。JavaScript可用于匹配每列的宽度。


2
这里有一个不错的解决方案(主要是CSS),它使用固定宽度列:http://www.imaputz.com/cssStuff/bulletVersion.html 此外,这里有一段jQuery代码,用于在单元格内容超过固定宽度时修复单元格宽度:
<script
  src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"
  type="text/javascript"></script>
<script>
$(function() {
  $('div.tableContainer').each(function() { // for each table
    var div = $(this);
    var widths = [];
    var changed = false;
    $('table>*>tr', div).each(function(tr_i) {
      $(this).children().each(function(i) {
        var w = $(this).width();
        if (w > widths[i]) {
            widths[i] = w;
            changed = true;
        }
      });
    }).each(function(tr_i) {
      if (changed)
      $(this).children().each(function(i) {
        var width = widths[i];
        // add some width for scrollbar
        if (tr_i == 0 && changed && i == widths.length-1) width += 16;
        // insert a div to ensure width
        $(this).append('<div style="width:'+width+'px; height:0px">&nbsp;</div>');
      });
    });
    div.width(div.children('table').width()).css('overflow-x', 'hidden');
  });
});
</script>

当使用非严格的DTD时,在IE中输出有些偏差。如果无法使用标准模式,请在CSS中调整宽度。
请注意,jQuery代码会在最后增加表格宽度,并禁用水平滚动条。您可能需要或不需要这样做。

2
您实际想要做的是使数据表格的可滚动,以便和自然保持固定。
虽然FF等浏览器很容易实现这一点:
tbody
{
    height: 100px; /* or whatever */
    overflow: auto;
    overflow-y: auto;
    overflow-x: hidden;
}

IE在一般情况下对tbody存在严重而复杂的问题。虽然可以通过表达式来解决,但这并不是一件简单的事情,并且具体取决于设计。


1
如果您正在寻找全面的跨浏览器实现,请查看YUI数据表。我相信这是通过创建另一个具有匹配列宽度的表来完成的。
似乎需要一些技巧来修复列宽。如果我记得正确,Firefox需要存在标签。
无论如何,在YUI DataTable(50k行)中使用了许多技巧。建议您查看它,并决定自己要走多远。

1

这个解决方案在Firefox和其他Gecko浏览器中使用CSS,在IE中使用CSS表达式。

http://home.tampabay.rr.com/bmerkey/examples/nonscroll-table-header.html

在Opera或Safari/Chrome中,页眉和页脚不固定,但整个表格是可滚动的,因此可以使用。请注意,作者的示例中给出了列的百分比宽度,但可以将其删除。

如果您想尝试Opera/Safari/Chrome的支持,请考虑给tbody设置display:block,并从那里开始。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接