是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
是否有跨浏览器的CSS/JavaScript技术来显示一个长HTML表,使列标题保持固定在屏幕上,而不随表体滚动。想想微软Excel中的“冻结窗格”效果。
我希望能够滚动表的内容,但总是能够在顶部看到列标题。
当前回答
使用最新版本的jQuery,并包含以下JavaScript代码。
$(window).scroll(function(){
$("id of the div element").offset({top:$(window).scrollTop()});
});
其他回答
很多人似乎都在寻找这个答案。我发现它隐藏在这里的另一个问题的答案:同步两个不同帧的表之间的列宽度,等等
在我尝试过的几十种方法中,这是我发现的唯一一种可靠的方法,可以让你有一个滚动的底部表,头部表具有相同的宽度。
以下是我是如何做到的,首先我改进了上面的jsfiddle来创建这个函数,它在td和th上都可以工作(以防绊倒其他人谁使用th来样式化他们的标题行)。
var setHeaderTableWidth= function (headertableid,basetableid) {
$("#"+headertableid).width($("#"+basetableid).width());
$("#"+headertableid+" tr th").each(function (i) {
$(this).width($($("#"+basetableid+" tr:first td")[i]).width());
});
$("#" + headertableid + " tr td").each(function (i) {
$(this).width($($("#" + basetableid + " tr:first td")[i]).width());
});
}
接下来,你需要创建两个表,注意头表应该有一个额外的TD,以便在顶部表中为滚动条留出空间,就像这样:
<table id="headertable1" class="input-cells table-striped">
<thead>
<tr style="background-color:darkgray;color:white;"><th>header1</th><th>header2</th><th>header3</th><th>header4</th><th>header5</th><th>header6</th><th></th></tr>
</thead>
</table>
<div id="resizeToBottom" style="overflow-y:scroll;overflow-x:hidden;">
<table id="basetable1" class="input-cells table-striped">
<tbody >
<tr>
<td>testdata</td>
<td>2</td>
<td>3</td>
<td>4</span></td>
<td>55555555555555</td>
<td>test</td></tr>
</tbody>
</table>
</div>
然后这样做:
setHeaderTableWidth('headertable1', 'basetable1');
$(window).resize(function () {
setHeaderTableWidth('headertable1', 'basetable1');
});
这是我在Stack Overflow上找到的唯一解决方案,可以解决许多类似的问题,在我所有的情况下都有效。
例如,我尝试了不与durandal工作的jQuery stickytables插件和谷歌代码项目https://code.google.com/p/js-scroll-table-header/issues/detail?id=2
其他涉及克隆表的解决方案性能很差,或者很糟糕,并不是在所有情况下都有效。
没有必要使用这些过于复杂的解决方案。只需像下面的例子一样创建两个表,并像这里描述的那样调用setHeaderTableWidth函数,然后嘣,你就完成了。
如果这对你不起作用,你可能在玩你的CSS box-sizing属性,你需要正确设置它。很容易意外地搞砸你的CSS内容。有很多事情都可能出错,所以要注意/小心。这种方法对我很有效。
一个更精致的纯CSS滚动表
到目前为止,我所见过的所有纯CSS解决方案——尽管它们可能很聪明——都缺乏一定程度的优化,或者在某些情况下不能正常工作。所以,我决定创建我自己的…
特点:
It's pure CSS, so no jQuery required (or any JavaScript code at all, for that matter) You can set the table width to a percent (a.k.a. "fluid") or a fixed value, or let the content determine its width (a.k.a. "auto") Column widths can also be fluid, fixed, or auto. Columns will never become misaligned with headers due to horizontal scrolling (a problem that occurs in every other CSS-based solution I've seen that doesn't require fixed widths). Compatible with all of the popular desktop browsers, including Internet Explorer back to version 8 Clean, polished appearance; no sloppy-looking 1-pixel gaps or misaligned borders; looks the same in all browsers
下面是一些显示流体和自动宽度选项的控件:
流体宽度和高度(适应屏幕大小):jsFiddle(注意,在此配置中,滚动条只在需要时显示,因此您可能必须缩小帧才能看到它) 自动宽度,固定高度(更容易与其他内容集成):jsFiddle
自动宽度,固定高度配置可能有更多的用例,所以我将在下面发布代码。
/* The following 'html' and 'body' rule sets are required only if using a % width or height*/ /*html { width: 100%; height: 100%; }*/ body { box-sizing: border-box; width: 100%; height: 100%; margin: 0; padding: 0 20px 0 20px; text-align: center; } .scrollingtable { box-sizing: border-box; display: inline-block; vertical-align: middle; overflow: hidden; width: auto; /* If you want a fixed width, set it here, else set to auto */ min-width: 0/*100%*/; /* If you want a % width, set it here, else set to 0 */ height: 188px/*100%*/; /* Set table height here; can be fixed value or % */ min-height: 0/*104px*/; /* If using % height, make this large enough to fit scrollbar arrows + caption + thead */ font-family: Verdana, Tahoma, sans-serif; font-size: 16px; line-height: 20px; padding: 20px 0 20px 0; /* Need enough padding to make room for caption */ text-align: left; color: black; } .scrollingtable * {box-sizing: border-box;} .scrollingtable > div { position: relative; border-top: 1px solid black; height: 100%; padding-top: 20px; /* This determines column header height */ } .scrollingtable > div:before { top: 0; background: cornflowerblue; /* Header row background color */ } .scrollingtable > div:before, .scrollingtable > div > div:after { content: ""; position: absolute; z-index: -1; width: 100%; height: 100%; left: 0; } .scrollingtable > div > div { min-height: 0/*43px*/; /* If using % height, make this large enough to fit scrollbar arrows */ max-height: 100%; overflow: scroll/*auto*/; /* Set to auto if using fixed or % width; else scroll */ overflow-x: hidden; border: 1px solid black; /* Border around table body */ } .scrollingtable > div > div:after {background: white;} /* Match page background color */ .scrollingtable > div > div > table { width: 100%; border-spacing: 0; margin-top: -20px; /* Inverse of column header height */ /*margin-right: 17px;*/ /* Uncomment if using % width */ } .scrollingtable > div > div > table > caption { position: absolute; top: -20px; /*inverse of caption height*/ margin-top: -1px; /*inverse of border-width*/ width: 100%; font-weight: bold; text-align: center; } .scrollingtable > div > div > table > * > tr > * {padding: 0;} .scrollingtable > div > div > table > thead { vertical-align: bottom; white-space: nowrap; text-align: center; } .scrollingtable > div > div > table > thead > tr > * > div { display: inline-block; padding: 0 6px 0 6px; /*header cell padding*/ } .scrollingtable > div > div > table > thead > tr > :first-child:before { content: ""; position: absolute; top: 0; left: 0; height: 20px; /*match column header height*/ border-left: 1px solid black; /*leftmost header border*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div > div:first-child, .scrollingtable > div > div > table > thead > tr > * + :before { position: absolute; top: 0; white-space: pre-wrap; color: white; /*header row font color*/ } .scrollingtable > div > div > table > thead > tr > * > div[label]:before, .scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);} .scrollingtable > div > div > table > thead > tr > * + :before { content: ""; display: block; min-height: 20px; /* Match column header height */ padding-top: 1px; border-left: 1px solid black; /* Borders between header cells */ } .scrollingtable .scrollbarhead {float: right;} .scrollingtable .scrollbarhead:before { position: absolute; width: 100px; top: -1px; /* Inverse border-width */ background: white; /* Match page background color */ } .scrollingtable > div > div > table > tbody > tr:after { content: ""; display: table-cell; position: relative; padding: 0; border-top: 1px solid black; top: -1px; /* Inverse of border width */ } .scrollingtable > div > div > table > tbody {vertical-align: top;} .scrollingtable > div > div > table > tbody > tr {background: white;} .scrollingtable > div > div > table > tbody > tr > * { border-bottom: 1px solid black; padding: 0 6px 0 6px; height: 20px; /* Match column header height */ } .scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;} .scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /* Alternate row color */ .scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /* Borders between body cells */ <div class="scrollingtable"> <div> <div> <table> <caption>Top Caption</caption> <thead> <tr> <th><div label="Column 1"/></th> <th><div label="Column 2"/></th> <th><div label="Column 3"/></th> <th> <!-- More versatile way of doing column label; requires two identical copies of label --> <div><div>Column 4</div><div>Column 4</div></div> </th> <th class="scrollbarhead"/> <!-- ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW --> </tr> </thead> <tbody> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr> </tbody> </table> </div> Faux bottom caption </div> </div> <!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
我用来冻结标题行的方法与d-Pixie的方法类似,因此请参阅他的帖子以获得解释。该技术存在大量错误和限制,只能通过大量额外的CSS和一两个额外的div容器来修复。
以下是对马克西米利安·希尔斯(Maximilian Hils)发布的答案的改进。
这个在ie11中没有任何闪烁:
var headerCells = tableWrap.querySelectorAll("thead td");
for (var i = 0; i < headerCells.length; i++) {
var headerCell = headerCells[i];
headerCell.style.backgroundColor = "silver";
}
var lastSTop = tableWrap.scrollTop;
tableWrap.addEventListener("scroll", function () {
var stop = this.scrollTop;
if (stop < lastSTop) {
// Resetting the transform for the scrolling up to hide the headers
for (var i = 0; i < headerCells.length; i++) {
headerCells[i].style.transitionDelay = "0s";
headerCells[i].style.transform = "";
}
}
lastSTop = stop;
var translate = "translate(0," + stop + "px)";
for (var i = 0; i < headerCells.length; i++) {
headerCells[i].style.transitionDelay = "0.25s";
headerCells[i].style.transform = translate;
}
});
两个div,一个用于头,一个用于数据。使数据div可滚动,并使用JavaScript将标题中的列的宽度设置为与数据中的宽度相同。我认为数据列的宽度应该是固定的,而不是动态的。
<html>
<head>
<script src="//cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script>
<script>
function stickyTableHead (tableID) {
var $tmain = $(tableID);
var $tScroll = $tmain.children("thead")
.clone()
.wrapAll('<table id="tScroll" />')
.parent()
.addClass($(tableID).attr("class"))
.css("position", "fixed")
.css("top", "0")
.css("display", "none")
.prependTo("#tMain");
var pos = $tmain.offset().top + $tmain.find(">thead").height();
$(document).scroll(function () {
var dataScroll = $tScroll.data("scroll");
dataScroll = dataScroll || false;
if ($(this).scrollTop() >= pos) {
if (!dataScroll) {
$tScroll
.data("scroll", true)
.show()
.find("th").each(function () {
$(this).width($tmain.find(">thead>tr>th").eq($(this).index()).width());
});
}
} else {
if (dataScroll) {
$tScroll
.data("scroll", false)
.hide()
;
}
}
});
}
$(document).ready(function () {
stickyTableHead('#tMain');
});
</script>
</head>
<body>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
gfgfdgsfgfdgfds<br/>
<table id="tMain" >
<thead>
<tr>
<th>1</th> <th>2</th><th>3</th> <th>4</th><th>5</th> <th>6</th><th>7</th> <th>8</th>
</tr>
</thead>
<tbody>
<tr><td>11111111111111111111111111111111111111111111111111111111</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5555555</td><td>66666666666</td><td>77777777777</td><td>8888888888888888</td></tr>
</tbody>
</table>
</body>
</html>