查看大表格时,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 选项卡中的表格上完美运行。
查看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;
并将您的网格包装到<div class="table-holder"></div>
。
注意:如果您的标题有可点击的控件,那么您可能需要添加更多的 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 表格标题始终显示在窗口顶部的主要内容,如果未能解决你的问题,请参考以下文章
当我从另一个窗体调用一个窗口时,它显示两个窗口一个在另一个的顶部