查看大表时,HTML表头始终在窗口顶部可见


169

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

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

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


页面是使用表格设计的吗?是否不可能先将其转换为div并单独为表格保留表格数据?

6
我最近写了一个执行此操作的插件:programmingdrunk.com/floatThead
mkoryak 2012年

1
除了下面投票最多的解决方案及其派生类之外,上面的@mkoryak的插件也相当不错。在完成“购物”之前,请务必也先看一​​看。
DanO 2014年

谢谢丹:)我也计划在下一个版本中使用一些辅助功能
mkoryak 2014年

我第二个@mkoryak floatThead插件-我能够快速集成它。非常感谢您的插件!
w5m

Answers:


67

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


是的,它适用于水平滚动,窗口滚动,内部滚动和窗口大小调整。
mkoryak

您可以在工作代码中添加小提琴吗?(我知道网站上有...)
Michel Ayres 2014年

12
我已经建立了一个巨大的演示/文档页面。为什么需要提琴呢?
mkoryak 2014年

5
@MustModify stackoverflow不是问我问题的好地方。在github上报告问题,即使只是关于如何使其工作的问题。病态通常会在一天之内回复到那里。这里病可能会在不到一年的时间内做出回应:)
mkoryak '16

1
@MustModify的价值不高,示例中表中的类均不相关。如我的文档所述,该插件不需要任何CSS或类即可工作。
mkoryak

135

我已经使用jQuery提出了概念验证解决方案。

在此处查看示例。

现在,我在Mercurial bitbucket存储库中获得了此代码。主文件是tables.html

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

2017年12月11日更新:我认为这不适用于当前的Firefox(57)和Chrome(63)。不知道什么时候,为什么停止工作,或如何修复它。但是现在,我认为Hendy Irawan接受的答案是优越的。


我需要这个来做我正在做的事情。很大的帮助,谢谢。对于我,我没有使用窗口,因为滚动窗格是html中的div。所以我不得不改变floatingHeaderRow.css("top", Math.min(scrollTop - offset.top, $(this).height() - floatingHeaderRow.height()) + "px");floatingHeaderRow.css("top", scrollTop + "px");与你的代码有表头进一步跳下页,最终消失在页。
Nalum

1
我正在尝试在我的桌子上实现这一点。我在标题宽度方面遇到问题。行中的数据是从db中提取的值,因此是随机长度。在滚动之前,标题将保持其自动继承的大小,但是一旦滚动,它将调整标题的大小以环绕标题名称,因此宽度要小得多,因此标题实际上不会在其各自的顶部跟踪柱。如何解决此问题?
JonYork

嗯,根据您的描述,我不确定。我建议1)如果可能,在线显示示例;2)在StackOverflow上提问。
Craig McQueen

@JonYork我有完全一样的问题。我的问题是在标头中使用<td>而不是<th>,因此它无法将每列的宽度应用于不存在的<th>(请参阅// Copy cell widths from original header代码的一部分)。@克雷格·麦昆(Craig McQueen),请修改您的答案,以便其他人都不会犯此错误。
aexl 2012年

@CraigMcQueen当我使用您的出色代码(谢谢)时,它在第二个表(它位于另一个选项卡(jQuery选项卡插件)的后面)上中断了。有什么想法吗?标头放置在最左侧,而不是跟随位置列。但是在第一个jQuery选项卡中的表上工作完美。
理查德·沙克(RichardŻak)2014年

68

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

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

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


1
制作jQuery插件的好主意。有两个问题:(1)它与水平滚动是否兼容?(2)当您向下滚动以使表格底部滚动离开窗口顶部时,它的行为如何?该示例不允许测试这些情况。
Craig McQueen

您的jsfiddle示例适用于tablesorter,但github上的代码无效。您是否需要修改表排序器代码?
ericslaw

克雷格(Craig),水平滚动应该不是问题,因为在滚动和调整大小时,标题可以在水平和垂直方向上重新定位。关于第二个问题:当表格离开视口时,标题将隐藏。
jmosbech 2011年

埃里克,这很奇怪。您是否尝试从Github打开/demo/tablesorter.htm?我尚未修改tablesorter代码,但是为了使其工作,您需要在tablesorter之前应用StickyTableHeader插件。
jmosbech 2011年

2
水平滚动并不完全有效,在滚动了一段距离后,thead在屏幕外滚动时的位置要比通常在桌子上正常放置时的位置靠左。
内森·菲利普斯

16

如果您针对的是符合现代css3的浏览器(浏览器支持: https : //caniuse.com/#feat=css-sticky),则可以使用position:sticky,它不需要JS并且不会破坏表布局的错位和同一列的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?

因为CSS规则是由浏览器呈现的,其写入顺序与您将它们写入CSS文件的顺序相同,因此,如果thead元素只有1行,则第一行同时也是最后一行,并且需要第一个子规则覆盖最后一个孩子。如果不是这样,那么您将使行距上边距有30 px的偏移量,我想这是您不希望的。

位置的一个已知问题:粘性是它不适用于thead元素或表格行:您必须定位到th个元素。跳出此问题将在将来的浏览器版本中解决。


第一个示例似乎在Firefox中不起作用(61)。但是,如果将粘性位置设置在剧院上,它就会这样做。
ewh '18

1
您可以thead tr+tr th定位第二行。
Teepeemm

5

可能的选择

js-floating-table-headers

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

在Drupal中

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

查看代码,似乎是通过名为的文件实现的tableheader.js。它将功能应用于所有带有类的表sticky-enabled

对于Drupal网站,我希望能够按tableheader.js原样使用该模块来处理用户内容。tableheader.js在Drupal的用户内容页面上似乎不存在。我在论坛上发布了一条消息,询问如何修改Drupal主题,使其可用。根据响应,tableheader.js可以将其添加到Drupal主题drupal_add_js()template.php,如下所示:

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

谢谢,您的Google代码链接对我非常有用。
Vilius Gaidelis,2012年

5

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

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

这对我有用,可能不是优雅的方法,但是确实有效。我将进行调查,以查看是否可以做得更好,但是它允许使用多个表。

仔细阅读溢出的内容,看看它是否符合您的需求


嗯,行不通,我将尝试解决此问题,但方法仍然存在,您必须使用以下溢出:autoproprety
Gab Royer

我很欣赏您的解决方案及其简单性,但是在我的问题中,我说:“注意:我已经看到一种解决方案,其中表数据区域可滚动而标头不滚动。这不是我想要的解决方案。”
克雷格·麦昆

@GabRoyer您引用的w3school页面不存在。
Farhan

他们似乎已经搬走了。已修正
Gab Royer 2013年

这种方法的另一个问题是,如果您需要使某些列适应其他内容,则可能会破坏它们与相应列标题的对齐方式。恕我直言,最好使用一种允许对内容进行动态管理的方法来解决此问题,该方法可以使列和相对标题保持完美对齐。因此,恕我直言,position = sticky是必经之路。
威利·旺卡

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中,其类属性等于“ 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中实现此目标,

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

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

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


+1是一种努力,但是对于具有大量数据的大型表来说,克隆整个东西是非常糟糕的……我想那将使加载时间增加一倍
khaverim 2014年

2

display: fixedthead部分中使用应该可以,但是因为它仅适用于视图中的当前表,因此您将需要JavaScript的帮助。这将很棘手,因为它将需要找出相对于视口的元素的滚动位置和位置,这是浏览器不兼容的主要方面之一。

看一下流行的JavaScript框架(jQuery,MooTools,YUI等),看看它们是否可以执行您想要的操作或使其更容易执行您想要的操作。


1
谢谢你的建议。我确实使用jQuery提出了解决方案-请参阅我的答案。
Craig McQueen

我尝试过此操作,并认为您的意思是位置而不是展示,但两者都没有为thead工作。
ericslaw

@ericslaw Ack-是的,我的意思是position: fixed。抱歉,它在Chrome中不起作用。
staticsan 2011年

通过忽略宽度样式弄乱了我的标题
pavel_kazlou

2

如果您使用全屏表格,则可能有兴趣将其设置为display:fixed; 和top:0; 或尝试通过CSS非常类似的方法。

更新资料

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

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

@ a_m0d,是的,但是请求听起来很混乱。要么我们误会了它,要么询问者不完全了解他想要什么。
桑普森


2

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


1
谢谢大卫,这是我在这个问题中发现的最好的方法
Tomasz Smykowski

0

概念证明你做是伟大的!但是我也发现这个jQuery插件似乎运行得很好。希望能帮助到你!


看起来好像实现了一个不同的功能。正如我在最初的问题中所说的:“注意:我已经看到一种解决方案,其中表数据区域可滚动而标头不滚动。这不是我想要的解决方案。”
Craig McQueen

2
您提到的尝试插件只是弄乱了我的表头。无法使用它。
pavel_kazlou

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>

4
我正在Firefox 8.0中进行尝试,但似乎没有任何作用。它有什么作用?
Craig McQueen

什么px啊 显示设备使用72 dpi时,是90年代人们使用的传统单位吗?
2013年

我同意:这非常令人沮丧,不幸的是,浏览器开发人员并未在每种情况下都遵守标准……而几年前甚至更糟!现在,一些问题已经解决,更多的浏览器以更标准的方式运行,但是仍然需要完成许多步骤:让我们祈祷并祈祷:-)
Willy wonka
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.