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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1030043/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 23:58:27  来源:igfitidea点击:

HTML table headers always visible at top of window when viewing a large table

htmlhtml-table

提问by Craig McQueen

I would like to be able to "tweak" an HTML table's presentation to add a single feature: when scrolling down through the page so that the table is on the screen but the header rows are off-screen, I would like the headers to remain visible at the top of the viewing area.

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

This would be conceptually like the "freeze panes" feature in Excel. However, an HTML page might contain several tables in it and I only would want it to happen for the table that is currently in-view, only while it is in-view.

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

Note: I've seen one solution where the table data area is made scrollable while the headers do not scroll. That's not the solution I'm looking for.

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

采纳答案by Hendy Irawan

Check out jQuery.floatThead(demos available) which is very cool, can work with DataTablestoo, and can even work inside an overflow: autocontainer.

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

回答by Craig McQueen

I've made a proof-of-concept solution using jQuery.

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

View sample here.

在此处查看示例。

I've now got this code in a Mercurial bitbucket repository. The main file is tables.html.

我现在在Mercurial bitbucket repository 中得到了这段代码。主文件是tables.html.

I'm aware of one issue with this: if the table contains anchors, and if you open the URL with the specified anchor in a browser, when the page loads, the row with the anchor will probably be obscured by the floating header.

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

Update 2017-12-11:I see this doesn't work with current Firefox (57) and Chrome (63). Not sure when and why this stopped working, or how to fix it. But now, I think the accepted answer by Hendy Irawanis superior.

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

回答by jmosbech

Craig, I refined your code a bit (among a few other things it's now using position:fixed) and wrapped it as a jQuery plugin.

克雷格,我稍微改进了你的代码(除了其他一些它现在使用的位置:固定)并将其包装为一个 jQuery 插件。

Try it out here: http://jsfiddle.net/jmosbech/stFcx/

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

And get the source here: https://github.com/jmosbech/StickyTableHeaders

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

回答by willy wonka

If you're targeting modern css3 compliant browsers (Browser support:https://caniuse.com/#feat=css-sticky) you can use position:sticky, which doesn't require JS and won't break the table layout miss-aligning th and td of the same column. Nor does it require fixed column width to work properly.

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

Example for a single header row:

单个标题行的示例:

thead th
{
    position: sticky;
    top: 0px;
}

For theads with 1 or 2 rows, you can use something like this:

对于 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 */
}

You might need to play a bit with the topproperty of the last child changing the number of pixels to match the height of the first row (+ the margin + the border + the padding, if any), so the second row sticks just down bellow the first one.

您可能需要使用最后一个孩子的top属性更改像素数以匹配第一行的高度(+ 边距 + 边框 + 填充,如果有的话),所以第二行会一直向下吼叫第一个。

Also both solutions work even if you have more than one table in the same page: the thelement of each one starts to be sticky when its top position is the one indicated into the css definition and just disappear when all the table scrolls down. So if there are more tables all work beautifully the same way.

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

Why to use last-child beforeand first-child afterin the css?

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

Because css rules are rendered by the browser in the same order as you write them into the css file and because of this if you have just 1 row into the thead element the first row is simultaneously the last row too and the first-child rule need to override the last-child one. If not you will have an offset of the row 30 px from the top margin which I suppose you don't want to.

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

A known problem of position: sticky is that it doesn't work on thead elements or table rows: you must target th elements. Hopping this issue will be solved on future browser versions.

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

回答by Gab Royer

I've encountered this problem very recently. Unfortunately, I had to do 2 tables, one for the header and one for the body. It's probably not the best approach ever but here goes:

我最近遇到了这个问题。不幸的是,我不得不做 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>

This worked for me, it's probably not the elegant way but it does work. I'll investigate so see if I can do something better, but it allows for multiple tables.

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

Go read on the overflowpropriety to see if it fits your need

阅读溢出属性,看看它是否符合您的需要

回答by Craig McQueen

Possible alternatives

可能的选择

js-floating-table-headers

js-浮动表头

js-floating-table-headers(Google Code)

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

In Drupal

在 Drupal 中

I have a Drupal 6 site. I was on the admin "modules" page, and noticed the tables had this exact feature!

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

Looking at the code, it seems to be implemented by a file called tableheader.js. It applies the feature on all tables with the class sticky-enabled.

看代码,好像是通过一个名为tableheader.js. 它将该功能应用于所有具有类的表sticky-enabled

For a Drupal site, I'd like to be able to make use of that tableheader.jsmodule as-is for user content. tableheader.jsdoesn't seem to be present on user content pages in Drupal. I posted a forum messageto ask how to modify the Drupal theme so it's available. According to a response, tableheader.jscan be added to a Drupal theme using drupal_add_js()in the theme's template.phpas follows:

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

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

回答by pgcan

This is really a tricky thing to have a sticky header on your table. I had same requirement but with asp:GridViewand then I found it really thought to have sticky header on gridview. There are many solutions available and it took me 3 days trying all the solution but none of them could satisfy.

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

The main issue that I faced with most of these solutions was the alignment problem. When you try to make the header floating, somehow the alignment of header cells and body cells get off track.

我在大多数这些解决方案中面临的主要问题是对齐问题。当您尝试使标题浮动时,不知何故标题单元格和正文单元格的对齐方式会偏离轨道。

With some solutions, I also got issue of getting header overlapped to first few rows of body, which cause body rows getting hidden behind the floating header.

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

So now I had to implement my own logic to achieve this, though I also not consider this as perfect solution but this could also be helpful for someone,

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

Below is the sample table.

下面是示例表。

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

Note: The table is wrapped into a DIV with class attribute equal to 'table-holder'.

注意:该表被包装成一个类属性等于“table-holder”的 DIV。

Below is the JQuery script that I added in my html page header.

下面是我在 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>

and at last below is the CSS class for bit of coloring purpose.

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

.table-holder
{
    height:200px;
    overflow:auto;
    border-width:0px;    
}

.customerTable thead
{
    background: #4b6c9e;        
    color:White;
}

So the whole idea of this logic is to place the table into a table holder div and create clone of that holder at client side when page loaded. Now hide the body of table inside clone holder and position the remaining header part over to original header.

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

Same solution also works for asp:gridview, you need to add two more steps to achieve this in gridview,

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

  1. In OnPrerender event of gridview object in your web page, set the table section of header row equal to TableHeader.

    if (this.HeaderRow != null)
    {
        this.HeaderRow.TableSection = TableRowSection.TableHeader;
    }
    
  2. And wrap your grid into <div class="table-holder"></div>.

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

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

Note: if your header has clickable controls then you may need to add some more jQuery script to pass the events raised in cloned header to original header. This code is already available in jQuery sticky-header plugin create by jmosbech

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

回答by merkuro

If you use a full screen table you are maybe interested in setting th to display:fixed; and top:0; or try a very similar approach via css.

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

Update

更新

Just quickly build up a working solution with iframes (html4.0). This example IS NOT standard conform, however you will easily be able to fix it:

只需使用 iframes (html4.0) 快速构建一个有效的解决方案。这个例子不符合标准,但是你可以很容易地修复它:

outer.html

外部.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

测试.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> 

回答by staticsan

Using display: fixedon the theadsection should work, but for it only work on the current table in view, you will need the help of JavaScript. And it will be tricky because it will need to figure out scrolling places and location of elements relative to the viewport, which is one of the prime areas of browser incompatibility.

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

Have a look at the popular JavaScript frameworks (jQuery, MooTools, YUI, etc etc.) to see if they can either do what you want or make it easier to do what you want.

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

回答by David Castro

The most simple answer only using CSS :D !!!

最简单的答案只使用 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>