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

时间:2009-06-23 00:17:12

标签: html html-table

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

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

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

12 个答案:

答案 0 :(得分:135)

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

View sample here.

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

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

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

答案 1 :(得分:67)

Craig,我对你的代码进行了一些改进(在其他几个方面,它现在使用position:fixed)并将其包装为jQuery插件。

在此处试试:http://jsfiddle.net/jmosbech/stFcx/

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

答案 2 :(得分:65)

查看非常酷的 jQuery.floatThead 演示),也可以使用DataTables,甚至可以在{{} {1}}容器。

答案 3 :(得分:6)

如果您定位现代浏览器(目前除了IE之外的任何浏览器),您可以使用position:sticky,它不需要JS并且不会破坏表格布局。它也不需要固定的列宽才能正常工作。

单个标题行的示例:

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 属性来改变像素数以匹配第一行的高度(+边距+边框+填充,如果任何一个),所以第二排刚刚落在第一排下方。

即使您在同一页面中有多个表,两个解决方案也都可以工作:当每个表的最高位置是css定义中指示的那个时,每个表的th元素开始变粘,当它们消失时所有的桌子向下滚动。因此,如果有更多的表格,所有表格的工作方式都相同。

浏览器支持: https://caniuse.com/#feat=css-sticky

答案 4 :(得分:5)

可能的替代方案

<强> JS-浮表头

js-floating-table-headers(Google代码)

在Drupal中

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

查看代码,它似乎是由一个名为tableheader.js的文件实现的。它在具有类sticky-enabled的所有表中应用该功能。

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

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

答案 5 :(得分:4)

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

<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适当的内容,了解它是否符合您的需求

答案 6 :(得分:3)

在桌面上设置一个粘性标题真的很棘手。我有相同的要求,但使用 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属性等于&#39; table-holder&#39;。

下面是我在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中添加两个步骤来实现这一点,

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

    if (this.HeaderRow != null)
    {
        this.HeaderRow.TableSection = TableRowSection.TableHeader;
    }
    
  2. 将您的网格包装到<div class="table-holder"></div>

  3. 注意:如果您的标头具有可点击控件,那么您可能需要添加一些jQuery脚本,以将克隆标头中引发的事件传递给原始标头。此代码已在jmosbech

    创建的jQuery sticky-header插件中提供

答案 7 :(得分:2)

如果您使用全屏表,您可能有兴趣设置显示: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" width="200" height="100"></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> 

答案 8 :(得分:2)

display: fixed部分使用thead应该有效,但是因为它只适用于视图中的当前表,您需要JavaScript的帮助。这将是棘手的,因为它需要找出相对于视口的元素的滚动位置和位置,这是浏览器不兼容的主要区域之一。

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

答案 9 :(得分:0)

你做的proof of concept很棒!但是我也发现this jQuery plugin似乎运作良好。希望它有所帮助!

答案 10 :(得分:0)

令人沮丧的是,在一个浏览器中运行良好的功能在其他浏览器中不起作用。以下适用于Firefox,但不适用于Chrome或IE:

<table width="80%">

 <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>

答案 11 :(得分:0)

仅使用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>