查看大表格时,HTML 表格标题始终显示在窗口顶部

Posted

技术标签:

【中文标题】查看大表格时,HTML 表格标题始终显示在窗口顶部【英文标题】:HTML table headers always visible at top of window when viewing a large table 【发布时间】:2010-11-05 00:40:27 【问题描述】:

我希望能够“调整” html 表格的演示文稿以添加单个功能:向下滚动页面以使表格在屏幕上但标题行不在屏幕上时,我想要标题在查看区域的顶部保持可见。

这在概念上类似于 Excel 中的“冻结窗格”功能。但是,一个 HTML 页面中可能包含多个表格,我只希望它发生在当前处于视图中的表格中,仅在它处于视图中时发生。

注意:我见过一种解决方案,其中表格数据区域可滚动,而标题不滚动。这不是我正在寻找的解决方案。

【问题讨论】:

您的页面是使用表格设计的吗?难道不能先将其转换为 div 并为表格单独保留表格数据吗? 我最近写了一个插件来做到这一点:programmingdrunk.com/floatThead 除了票数最高的解决方案及其下面的衍生方案之外,上面@mkoryak 的插件也相当不错。在完成“购物”之前,请务必查看一下。 谢谢 dan :) 我也为下一个版本计划了一些重要功能 我支持@mkoryak floatThead 插件——我能够迅速集成它。非常感谢插件! 【参考方案1】:

我使用jQuery 制作了一个概念验证解决方案。

View sample here.

我现在在Mercurial bitbucket repository 中获得了此代码。主文件为tables.html

我知道一个问题:如果表格包含锚点,并且如果您在浏览器中打开带有指定锚点的 URL,当页面加载时,带有锚点的行可能会被浮动遮挡标题。

2017-12-11 更新:我发现这不适用于当前的 Firefox (57) 和 Chrome (63)。不确定何时以及为什么停止工作,或者如何解决它。但现在,我认为accepted answer by Hendy Irawan 更胜一筹。

【讨论】:

我正在做的事情需要这个。很大的帮助,谢谢。我没有使用窗口,因为滚动窗格是 html 中的 div。所以我不得不将floatingHeaderRow.css("top", Math.min(scrollTop - offset.top, $(this).height() - floatingHeaderRow.height()) + "px"); 更改为floatingHeaderRow.css("top", scrollTop + "px");,因为你的表头在页面下方跳得更远,最终从页面上消失。 我正在尝试在我的表中实现这一点。我遇到标题宽度问题。行中的数据是从数据库中提取的值,因此是随机长度。在滚动之前,标题处于其自动继承的大小,但是一旦滚动,它会调整标题的大小以环绕标题名称,因此宽度要小得多,因此标题实际上不会在它们各自的顶部跟踪柱子。我该如何解决这个问题? 嗯,我不确定,根据您的描述。我建议1)如果可能的话,在网上展示一个例子; 2) 在 *** 上提问。 @JonYork 我遇到了完全相同的问题。我的问题是在标题中使用 而不是 所以它不能将每列的宽度应用于不存在的 (参见代码的// Copy cell widths from original header 部分)。 @Craig McQueen,请编辑您的答案,以免其他人犯此错误。 @CraigMcQueen 当我使用您很棒的代码(谢谢)时,它会在我拥有的第二个表上中断,该表位于另一个选项卡(jQuery 选项卡插件)后面。有什么想法吗?标题放置在最左侧,而不是跟随位置列。但在第一个 jQuery 选项卡中的表格上完美运行。 【参考方案2】:

查看jQuery.floatThead提供演示),它非常酷,也可以与DataTables 一起使用,甚至可以在overflow: auto 容器中工作。

【讨论】:

是的,它适用于水平滚动、窗口滚动、内部滚动和窗口大小调整。 你能添加一个带有工作代码的小提琴吗? (我知道网站里有……) 我已经建立了一个巨大的演示/文档页面。为什么需要小提琴? @MustModify *** 不是问我问题的好地方。在 github 上报告一个问题,即使它只是一个关于如何让它工作的问题。生病通常会在一天之内回复。在这里可能会在不到一年的时间内做出反应:) @MustModify 就其价值而言,示例中表格上的所有类都不相关。正如我的文档所说,该插件不需要任何 css 或类即可工作。【参考方案3】:

克雷格,我对你的代码进行了一些改进(在其他一些事情中,它现在使用 position:fixed)并将它包装成一个 jQuery 插件。

在这里试试:http://jsfiddle.net/jmosbech/stFcx/

并在此处获取源代码:https://github.com/jmosbech/StickyTableHeaders

【讨论】:

制作一个 jQuery 插件的好主意。几个问题:(1)它是否适用于水平滚动? (2) 当您向下滚动以使表格底部从窗口顶部滚动时,它的行为如何?该示例不允许测试这些情况。 您的 jsfiddle 示例适用于 tablesorter,但 github 上的代码不能。您是否必须修改 tablesorter 代码? 克雷格,水平滚动应该不是问题,因为标题在滚动和调整大小时水平和垂直都重新定位。至于你的第二个问题:当表格离开视口时,标题是隐藏的。 埃里克,这很奇怪。您是否尝试从 Github 打开 /demo/tablesorter.htm ?我没有修改tablesorter代码,但是为了让它工作你需要在tablesorter之前应用StickyTableHeader插件。 水平滚动不太有效,在滚动一段距离后,在屏幕外滚动时,thead 的位置比通常作为表格的一部分定位时更靠左。【参考方案4】:

如果您的目标是现代 css3 兼容浏览器(浏览器支持: https://caniuse.com/#feat=css-sticky),您可以使用 position:sticky,它不需要 JS 并且不会破坏表格布局 -对齐同一列的 th 和 td。它也不需要固定的列宽才能正常工作。

单个标题行的示例:

thead th

    position: sticky;
    top: 0px;

对于 1 行或 2 行的标题,您可以使用以下内容:

thead > :last-child th

    position: sticky;
    top: 30px; /* This is for all the the "th" elements in the second row, (in this casa is the last child element into the thead) */


thead > :first-child th

    position: sticky;
    top: 0px; /* This is for all the the "th" elements in the first child row */

您可能需要对最后一个子项的 top 属性进行一些更改,以更改像素数以匹配第一行的高度(+ 边距 + 边框 + 内边距,如果任何),所以第二行紧挨着第一行。

即使您在同一页面中有多个表,这两种解决方案也都有效:每个表的 th 元素在其顶部位置是 css 定义中指示的那个时开始变得粘滞,并且当所有表格向下滚动。因此,如果有更多的表都可以以相同的方式完美地工作。

为什么在css中使用last-child before和first-child after

因为 css 规则由浏览器以与您将它们写入 css 文件的顺序相同的顺序呈现,因此,如果您在 thead 元素中只有 1 行,则第一行也是最后一行,并且第一个 -子规则需要覆盖最后一个子规则。如果不是,您将从上边距偏移 30 px 的行,我想您不想这样做。

position:sticky 的一个已知问题是它不适用于 thead 元素或表格行:您必须定位 th 元素。跳跃这个问题将在未来的浏览器版本中得到解决。

【讨论】:

第一个示例似乎不适用于 Firefox (61)。但是,如果在广告上设置了粘性位置,它会这样做。 您可以使用thead tr+tr th 来定位第二行。【参考方案5】:

可能的替代方案

js-floating-table-headers

js-floating-table-headers(谷歌代码)

在 Drupal 中

我有一个 Drupal 6 站点。我在管理“模块”页面上,注意到表格具有这个确切的功能!

看代码,好像是通过一个叫tableheader.js的文件实现的。它将该功能应用于所有具有 sticky-enabled 类的表。

对于 Drupal 站点,我希望能够将 tableheader.js 模块原样用于用户内容。 tableheader.js 似乎没有出现在 Drupal 的用户内容页面上。我发布了forum message 询问如何修改 Drupal 主题以使其可用。根据回复,tableheader.js 可以使用主题的template.php 中的drupal_add_js() 添加到 Drupal 主题,如下所示:

drupal_add_js('misc/tableheader.js', 'core');

【讨论】:

您的 Google 代码链接对我非常有用,tahnks。【参考方案6】:

我最近遇到了这个问题。不幸的是,我不得不做两张桌子,一张用于标题,一张用于正文。这可能不是有史以来最好的方法,但这里是:

<html>
<head>
    <title>oh hai</title>
</head>
<body>
    <table id="tableHeader">
        <tr>
            <th style="width:100px; background-color:#CCCCCC">col header</th>
            <th style="width:100px; background-color:#CCCCCC">col header</th>
        </tr>
    </table>
    <div style="height:50px; overflow:auto; width:250px">
        <table>
            <tr>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data1</td>
            </tr>
            <tr>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
                <td style="height:50px; width:100px; background-color:#DDDDDD">data2</td>
            </tr>
        </table>
    </div>
</body>
</html>

这对我有用,它可能不是优雅的方式,但它确实有效。我会调查一下,看看我是否可以做得更好,但它允许多个表。

阅读overflow 的规定,看看它是否符合您的需要

【讨论】:

嗯不工作,我会尝试解决这个问题,但方法仍然存在,你必须使用溢出:自动属性 我很欣赏您的解决方案及其简单性,但是在我的问题中我说“注意:我见过一种解决方案,其中表格数据区域可滚动而标题不滚动。这不是解决方案我在找。” @GabRoyer 您引用的 w3school 页面不存在。 他们似乎已经搬走了它。固定 这种方法的另一个问题是,如果您需要使某些列适应其他内容,您可能会破坏它们与相应列标题的对齐。恕我直言,最好用一种方法来解决这个问题,该方法允许对内容进行某种动态管理,以保持列和相关标题的完美对齐。所以恕我直言 position=sticky 是要走的路。【参考方案7】:

仅使用 CSS 的最简单答案 :D !!!

table 
  /* Not required only for visualizing */
  border-collapse: collapse;
  width: 100%;


table thead tr th 
  /* you could also change td instead th depending your html code */
  background-color: green;
  position: sticky;
  z-index: 100;
  top: 0;


td 
  /* Not required only for visualizing */
  padding: 1em;
<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>data</td>
       <td>data</td>
       <td>data</td>
     </tr>
     <tr>
       <td>david</td>
       <td>castro</td>
       <td>rocks!</td>
     </tr>
  </tbody>
</table>

【讨论】:

谢谢大卫,这是我在这个问题中找到的最好的方法【参考方案8】:

thead 部分上使用display: fixed 应该可以工作,但是因为它只能在视图中的当前表上工作,你需要javascript 的帮助。这会很棘手,因为它需要确定元素相对于视口的滚动位置和位置,这是浏览器不兼容的主要领域之一。

看看流行的 JavaScript 框架(jQuery、MooTools、YUI 等),看看它们是否可以做你想做的事,或者让你做你想做的事变得更容易。

【讨论】:

感谢您的建议。我确实使用 jQuery 制作了一个解决方案——请参阅我的答案。 我试过这个,我认为你的意思是位置而不是显示,但在 chome 中都没有为thead 工作。 @ericslaw Ack - 是的,我的意思是position: fixed。抱歉,它在 Chrome 中不起作用。 忽略宽度样式弄乱了我的标题【参考方案9】:

在你的桌子上有一个粘性标题确实是一件棘手的事情。我有同样的要求,但使用 asp:GridView 然后我发现它真的认为在 gridview 上有粘性标题。有很多可用的解决方案,我花了 3 天时间尝试所有解决方案,但没有一个能满足。

我在这些解决方案中遇到的主要问题是对齐问题。当您尝试使标题浮动时,标题单元格和正文单元格的对齐会以某种方式偏离轨道。

通过一些解决方案,我还遇到了标题与正文的前几行重叠的问题,这导致正文行隐藏在浮动标题后面。

所以现在我必须实现自己的逻辑来实现这一点,虽然我也不认为这是完美的解决方案,但这也可能对某人有所帮助,

下面是示例表。

<div class="table-holder">
        <table id="MyTable" cellpadding="4" cellspacing="0" border="1px" class="customerTable">
            <thead>
                <tr><th>ID</th><th>First Name</th><th>Last Name</th><th>DOB</th><th>Place</th></tr>
            </thead>
            <tbody>
                <tr><td>1</td><td>Customer1</td><td>LastName</td><td>1-1-1</td><td>SUN</td></tr>
                <tr><td>2</td><td>Customer2</td><td>LastName</td><td>2-2-2</td><td>Earth</td></tr>
                <tr><td>3</td><td>Customer3</td><td>LastName</td><td>3-3-3</td><td>Mars</td></tr>
                <tr><td>4</td><td>Customer4</td><td>LastName</td><td>4-4-4</td><td>Venus</td></tr>
                <tr><td>5</td><td>Customer5</td><td>LastName</td><td>5-5-5</td><td>Saturn</td></tr>
                <tr><td>6</td><td>Customer6</td><td>LastName</td><td>6-6-6</td><td>Jupitor</td></tr>
                <tr><td>7</td><td>Customer7</td><td>LastName</td><td>7-7-7</td><td>Mercury</td></tr>
                <tr><td>8</td><td>Customer8</td><td>LastName</td><td>8-8-8</td><td>Moon</td></tr>
                <tr><td>9</td><td>Customer9</td><td>LastName</td><td>9-9-9</td><td>Uranus</td></tr>
                <tr><td>10</td><td>Customer10</td><td>LastName</td><td>10-10-10</td><td>Neptune</td></tr>
            </tbody>
        </table>
    </div>

注意:表格被包装成一个DIV,其class属性等于'table-holder'。

下面是我在 html 页面标题中添加的 JQuery 脚本。

<script src="../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script>
<script src="../Scripts/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(document).ready(function () 
        //create var for table holder
        var originalTableHolder = $(".table-holder");
        // set the table holder's with
        originalTableHolder.width($('table', originalTableHolder).width() + 17);
        // Create a clone of table holder DIV
        var clonedtableHolder = originalTableHolder.clone();

        // Calculate height of all header rows.
        var headerHeight = 0;
        $('thead', originalTableHolder).each(function (index, element) 
            headerHeight = headerHeight + $(element).height();
        );

        // Set the position of cloned table so that cloned table overlapped the original
        clonedtableHolder.css('position', 'relative');
        clonedtableHolder.css('top', headerHeight + 'px');

        // Set the height of cloned header equal to header height only so that body is not visible of cloned header
        clonedtableHolder.height(headerHeight);
        clonedtableHolder.css('overflow', 'hidden');

        // reset the ID attribute of each element in cloned table
        $('*', clonedtableHolder).each(function (index, element) 
            if ($(element).attr('id')) 
                $(element).attr('id', $(element).attr('id') + '_Cloned');
            
        );

        originalTableHolder.css('border-bottom', '1px solid #aaa');

        // Place the cloned table holder before original one
        originalTableHolder.before(clonedtableHolder);
    );
</script>

最后是用于着色目的的 CSS 类。

.table-holder

    height:200px;
    overflow:auto;
    border-width:0px;    


.customerTable thead

    background: #4b6c9e;        
    color:White;

因此,此逻辑的整个想法是将表格放入表格持有人 div 中,并在页面加载时在客户端创建该持有人的克隆。现在将表格主体隐藏在克隆支架内,并将剩余的标题部分放置在原始标题上。

同样的解决方案也适用于 asp:gridview,您需要在 gridview 中再添加两个步骤来实现这一点,

    在你的网页的gridview对象的OnPrerender事件中,设置标题行的表格部分等于TableHeader。

    if (this.HeaderRow != null)
    
        this.HeaderRow.TableSection = TableRowSection.TableHeader;
    
    

    并将您的网格包装到&lt;div class="table-holder"&gt;&lt;/div&gt;

注意:如果您的标题有可点击的控件,那么您可能需要添加更多的 jQuery 脚本来将克隆标题中引发的事件传递给原始标题。此代码已在 jmosbech 创建的 jQuery 粘头插件中可用

【讨论】:

+1 努力,但对于包含大量数据的大型表,克隆整个东西是非常糟糕的......我想这会使加载时间加倍【参考方案10】:

如果您使用全屏表格,您可能有兴趣将 th 设置为 display:fixed;和顶部:0;或通过 css 尝试非常相似的方法。

更新

只需使用 iframe (html4.0) 快速构建一个可行的解决方案。此示例不符合标准,但是您可以轻松修复它:

outer.html

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">   
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">     
    <head>      
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />   
        <title>Outer</title>
  <body>
    <iframe src="test.html"  ></iframe>
    </body>
</html> 

test.html

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">   
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">     
    <head>      
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />   
        <title>Floating</title>
    <style type="text/css">
      .content
        position:relative; 
      

      thead
        background-color:red;
        position:fixed; 
        top:0;
      
    </style>
  <body>
    <div class="content">      
      <table>
        <thead>
          <tr class="top"><td>Title</td></tr>
        </head>
        <tbody>
          <tr><td>a</td></tr>
          <tr><td>b</td></tr>
          <tr><td>c</td></tr>
          <tr><td>d</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
          <tr><td>e</td></tr>
        </tbody>
      </table>
    </div>
    </body>
</html> 

【讨论】:

@a_m0d,是的......但这个请求听起来很混乱。要么我们误解了它,要么提问者没有完全理解他想要什么。 这是另一个使用一些javascript的解决方案imaputz.com/cssStuff/bigFourVersion.html【参考方案11】:

你制作的proof of concept 太棒了!但是我也发现this jQuery plugin 似乎工作得很好。希望对您有所帮助!

【讨论】:

这看起来好像实现了一个不同的功能。正如我在最初的问题中所说:“注意:我见过一种解决方案,其中表格数据区域可滚动,而标题不滚动。这不是我正在寻找的解决方案。” 你提到的尝试插件只是弄乱了我的表头。无法使用。【参考方案12】:

令人沮丧的是,在一种浏览器中效果很好的东西在其他浏览器中却不起作用。以下适用于 Firefox,但不适用于 Chrome 或 IE:

<table >

 <thead>

 <tr>
  <th>Column 1</th>
  <th>Column 2</th>
  <th>Column 3</th>
 </tr>

 </thead>

 <tbody style="height:50px; overflow:auto">

  <tr>
    <td>Cell A1</td>
    <td>Cell B1</td>
    <td>Cell C1</td>
  </tr>

  <tr>
    <td>Cell A2</td>
    <td>Cell B2</td>
    <td>Cell C2</td>
  </tr>

  <tr>
    <td>Cell A3</td>
    <td>Cell B3</td>
    <td>Cell C3</td>
  </tr>

 </tbody>

</table>

【讨论】:

我正在 Firefox 8.0 中尝试它,它似乎没有做任何事情。它有什么作用? 什么是px?是不是 90 年代人们使用的传统单位,当时显示设备的分辨率为 72 dpi? 我同意:这非常令人沮丧,不幸的是浏览器开发人员并不在所有情况下都遵守标准......几年前甚至更糟!现在一些问题已经解决,更多的浏览器以更标准化的方式运行,但仍有许多步骤需要完成:让我们希望和祈祷:-)

以上是关于查看大表格时,HTML 表格标题始终显示在窗口顶部的主要内容,如果未能解决你的问题,请参考以下文章

当我从另一个窗体调用一个窗口时,它显示两个窗口一个在另一个的顶部

如何在滚动表格视图期间始终将表格视图的第一个单元格保持在其表格视图的顶部

如何在html表格上显示滚动条

excel表格中如何让第一列始终显示并打印

Excel中怎么进行首行冻结?

仅使用 HTML 和 CSS 在图像顶部显示表格