当用户使用jQuery将其滚动到视图之外时,表头保持固定在顶部

我试图设计一个HTML表,其中标题将停留在页面的顶部时,只有当用户滚动它的视图。 例如,表格可能从页面向下500像素,我怎样才能做到这一点,以便如果用户滚动标题的视图(浏览器不再在Windows视图中检测到它),它将保持在顶部? 任何人都可以给我一个JavaScript的解决方案呢?

<table> <thead> <tr> <th>Col1</th> <th>Col2</th> <th>Col3</th> </tr> </thead> <tbody> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> </tbody> </table> 

所以在上面的例子中,我希望<thead>在页面不<thead>下滚动页面。

重要提示:我不是寻找一个解决方案,其中<tbody>将有一个滚动条(溢出:自动)。

您可以通过点击window上的scroll事件处理程序来执行此类操作,并使用具有固定位置的另一个table来在页面顶部显示标题。

HTML:

 <table id="header-fixed"></table> 

CSS:

 #header-fixed { position: fixed; top: 0px; display:none; background-color:white; } 

JavaScript的:

 var tableOffset = $("#table-1").offset().top; var $header = $("#table-1 > thead").clone(); var $fixedHeader = $("#header-fixed").append($header); $(window).bind("scroll", function() { var offset = $(this).scrollTop(); if (offset >= tableOffset && $fixedHeader.is(":hidden")) { $fixedHeader.show(); } else if (offset < tableOffset) { $fixedHeader.hide(); } }); 

当用户向下滚动到足以隐藏原来的桌面时,这将显示桌面的头部。 当用户再次向上滚动页面时,会再次隐藏。

工作示例: http : //jsfiddle.net/andrewwhitaker/fj8wM/

那么,我试图获得同样的效果,而不是固定大小的列或整个表的固定高度。

我提出的解决方案是一个黑客。 它包括复制整个表格,然后隐藏除标题之外的所有内容,并使其具有固定的位置。

HTML

 <div id="table-container"> <table id="maintable"> <thead> <tr> <th>Col1</th> <th>Col2</th> <th>Col3</th> </tr> </thead> <tbody> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>some really long line here instead</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> </tbody> </table> <div id="bottom_anchor"></div> </div> 

CSS

 body { height: 1000px; } thead{ background-color:white; } 

JavaScript的

 function moveScroll(){ var scroll = $(window).scrollTop(); var anchor_top = $("#maintable").offset().top; var anchor_bottom = $("#bottom_anchor").offset().top; if (scroll>anchor_top && scroll<anchor_bottom) { clone_table = $("#clone"); if(clone_table.length == 0){ clone_table = $("#maintable").clone(); clone_table.attr('id', 'clone'); clone_table.css({position:'fixed', 'pointer-events': 'none', top:0}); clone_table.width($("#maintable").width()); $("#table-container").append(clone_table); $("#clone").css({visibility:'hidden'}); $("#clone thead").css({'visibility':'visible','pointer-events':'auto'}); } } else { $("#clone").remove(); } } $(window).scroll(moveScroll); 

看到这里: http : //jsfiddle.net/QHQGF/7/

编辑:更新代码,以便thead可以接收指针事件(所以在标题中的按钮和链接仍然工作)。 这解决了luhfluh和Joe M.报告的问题

新的jsfiddle在这里: http : //jsfiddle.net/cjKEx/

我能够解决问题,改变列的宽度。 我从上面的Andrew的解决方案开始(非常感谢!),然后添加一个小循环来设置克隆td的宽度:

 $("#header-fixed td").each(function(index){ var index2 = index; $(this).width(function(index2){ return $("#table-1 td").eq(index).width(); }); }); 

这样可以解决问题,而无需克隆整个表格并隐藏主体。 我是全新的JavaScript和jQuery(和堆栈溢出),所以任何意见表示赞赏。

我写了一个插件来做到这一点。 我已经做了大约一年的时间,我认为它可以很好地处理所有的情况:

  • 在溢出的容器内滚动
  • 在一个窗口内滚动
  • 注意调整窗口大小时会发生什么情况
  • 保持你的事件绑定到标题
  • 最重要的是它并不强迫你改变你的表的CSS来使其工作

以下是一些演示/文档:
http://mkoryak.github.io/floatThead/

这是迄今为止我找到的具有固定表头的最佳解决方案。

CSS

 .fixed{ top:0; position:fixed; width:auto; display:none; border:none; background-color:white; } 

JavaScript的

 ;(function($) { $.fn.fixMe = function() { return this.each(function() { var $this = $(this), $t_fixed; function init() { $this.wrap('<div class="container" />'); $t_fixed = $this.clone(); $t_fixed.find("tbody").remove().end().addClass("fixed").insertBefore($this); resizeFixed(); } function resizeFixed() { $t_fixed.find("th").each(function(index) { $(this).css("width",$this.find("th").eq(index).outerWidth()+"px"); }); } function scrollFixed() { var offset = $(this).scrollTop(), tableOffsetTop = $this.offset().top, tableOffsetBottom = tableOffsetTop + $this.height() - $this.find("thead").height(); if(offset < tableOffsetTop || offset > tableOffsetBottom) $t_fixed.hide(); else if(offset >= tableOffsetTop && offset <= tableOffsetBottom && $t_fixed.is(":hidden")) $t_fixed.show(); } $(window).resize(resizeFixed); $(window).scroll(scrollFixed); init(); }); }; })(jQuery); $(document).ready(function(){ $("table").fixMe(); }); }); 

来源: http : //codepen.io/jgx/pen/wiIGc

最好的解决方案是使用这个jQuery插件:

https://github.com/jmosbech/StickyTableHeaders

这个插件对我们很好,我们尝试了很多其他的解决方案。 我们在IE,Chrome和Firefox中测试它

纯CSS(2017年5月没有IE和Edge支持):

 table thead { position: -webkit-sticky; position: sticky; top: 0; z-index: 5; background: #fff; } 

我找到了一个名为Sticky Table Headers的简单jQuery库。 两行代码,它正是我想要的。 上面的解决方案不管理列的宽度,所以如果你的表单元占用大量的空间,那么这个持久性表头的结果大小就不能匹配你的表的宽度。

http://plugins.jquery.com/StickyTableHeaders/

使用信息在这里: https : //github.com/jmosbech/StickyTableHeaders

那么,在审查了所有可用的解决方案后,我写了一个插件,可以冻结页面或容器顶部的任何行(不仅仅是th)。 这非常简单,速度非常快。 随意使用它。 http://maslianok.github.io/stickyRows/

我也经历了同样的问题,边界格式化不会显示使用的代码的代码,但一些小的修复,现在的表是可扩展的,并显示您可能添加的所有CSS样式规则。

给CSS添加:

 #maintable{width: 100%} 

那么这里是新的javascript:

  function moveScroll(){ var scroll = $(window).scrollTop(); var anchor_top = $("#maintable").offset().top; var anchor_bottom = $("#bottom_anchor").offset().top; if (scroll > anchor_top && scroll < anchor_bottom) { clone_table = $("#clone"); if(clone_table.length === 0) { clone_table = $("#maintable").clone(); clone_table.attr({id: "clone"}) .css({ position: "fixed", "pointer-events": "none", top:0 }) .width($("#maintable").width()); $("#table-container").append(clone_table); // dont hide the whole table or you lose border style & // actively match the inline width to the #maintable width if the // container holding the table (window, iframe, div) changes width $("#clone").width($("#maintable").width()); // only the clone thead remains visible $("#clone thead").css({ visibility:"visible" }); // clone tbody is hidden $("#clone tbody").css({ visibility:"hidden" }); // add support for a tfoot element // and hide its cloned version too var footEl = $("#clone tfoot"); if(footEl.length){ footEl.css({ visibility:"hidden" }); } } } else { $("#clone").remove(); } } $(window).scroll(moveScroll); 

这是一个以接受的答案为基础的解决方案。 它更正了:列宽,匹配的表格样式,以及表格在容器div中滚动的时间。

用法

确保你的表有一个<thead>标签,因为只有内容会被修复。

 $("#header-fixed").fixHeader(); 

JavaSript

 //Custom JQuery Plugin (function ($) { $.fn.fixHeader = function () { return this.each(function () { var $table = $(this); var $sp = $table.scrollParent(); var tableOffset = $table.position().top; var $tableFixed = $("<table />") .prop('class', $table.prop('class')) .css({ position: "fixed", "table-layout": "fixed", display: "none", "margin-top": "0px" }); $table.before($tableFixed); $tableFixed.append($table.find("thead").clone()); $sp.bind("scroll", function () { var offset = $(this).scrollTop(); if (offset > tableOffset && $tableFixed.is(":hidden")) { $tableFixed.show(); var p = $table.position(); var offset = $sp.offset(); //Set the left and width to match the source table and the top to match the scroll parent $tableFixed.css({ left: p.left + "px", top: (offset ? offset.top : 0) + "px", }).width($table.width()); //Set the width of each column to match the source table $.each($table.find('th, td'), function (i, th) { $($tableFixed.find('th, td')[i]).width($(th).width()); }); } else if (offset <= tableOffset && !$tableFixed.is(":hidden")) { $tableFixed.hide(); } }); }); }; })(jQuery); 

这将帮助你有一个固定的标题,也可以用数据水平滚动。

 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Shubh</title> <script type="text/javascript"> var lastSeen = [ 0, 0 ]; function checkScroll(div1, div2) { if (!div1 || !div2) return; var control = null; if (div1.scrollLeft != lastSeen[0]) control = div1; else if (div2.scrollLeft != lastSeen[1]) control = div2; if (control == null) return; else div1.scrollLeft = div2.scrollLeft = control.scrollLeft; lastSeen[0] = div1.scrollLeft; lastSeen[1] = div2.scrollLeft; } window .setInterval( "checkScroll(document.getElementById('innertablediv'), document.getElementById('headertable'))", 1); </script> <style type="text/css"> #full { width: 400px; height: 300px; } #innertablediv { height: 200px; overflow: auto; } #headertable { overflow: hidden; } </style> </head> <body> <div id="full"> <div id="headertable"> <table border="1" bgcolor="grey" width="150px" id="headertable"> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>&nbsp;&nbsp;&nbsp;</td> </tr> </table> </div> <div id="innertablediv"> <table border="1" id="innertableid"> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> <tr> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> <td>shubh, ansh</td> </tr> </table> </div> </div> </body> </html> 
 function fix_table_header_position(){ var width_list = []; $("th").each(function(){ width_list.push($(this).width()); }); $("tr:first").css("position", "absolute"); $("tr:first").css("z-index", "1000"); $("th, td").each(function(index){ $(this).width(width_list[index]); }); $("tr:first").after("<tr height=" + $("tr:first").height() + "></tr>");} 

这是我的解决方案

晚了一点,但是这里有一个实现,可以在同一个页面上使用多个表格,并且可以免费使用(使用requestAnimationFrame)。 也不需要在列上提供任何宽度。 水平滚动也起作用。

头文件是在一个div中定义的,所以你可以自由地添加任何标记(如按钮),如果需要的话。 这是所有需要的HTML:

 <div class="tbl-resp"> <table id="tbl1" class="tbl-resp__tbl"> <thead> <tr> <th>col 1</th> <th>col 2</th> <th>col 3</th> </tr> </thead> </table> </div> 

https://jsfiddle.net/lloydleo/bk5pt5gs/

在这个解决方案中,固定头部是动态创建的,内容和样式是从THEAD克隆的

所有你需要的是两行例如:

var $myfixedHeader = $("#Ttodo").FixedHeader(); //create fixed header $(window).scroll($myfixedHeader.moveScroll); //bind function to scroll event

我的jQuery插件FixedHeader和getStyleObject提供下面你可以把文件.js

 // JAVASCRIPT /* * getStyleObject Plugin for jQuery JavaScript Library * From: http://upshots.org/?p=112 Basic usage: $.fn.copyCSS = function(source){ var styles = $(source).getStyleObject(); this.css(styles); } */ (function($){ $.fn.getStyleObject = function(){ var dom = this.get(0); var style; var returns = {}; if(window.getComputedStyle){ var camelize = function(a,b){ return b.toUpperCase(); }; style = window.getComputedStyle(dom, null); for(var i = 0, l = style.length; i < l; i++){ var prop = style[i]; var camel = prop.replace(/\-([az])/g, camelize); var val = style.getPropertyValue(prop); returns[camel] = val; }; return returns; }; if(style = dom.currentStyle){ for(var prop in style){ returns[prop] = style[prop]; }; return returns; }; return this.css(); } })(jQuery); //Floating Header of long table PiotrC (function ( $ ) { var tableTop,tableBottom,ClnH; $.fn.FixedHeader = function(){ tableTop=this.offset().top, tableBottom=this.outerHeight()+tableTop; //Add Fixed header this.after('<table id="fixH"></table>'); //Clone Header ClnH=$("#fixH").html(this.find("thead").clone()); //set style ClnH.css({'position':'fixed', 'top':'0', 'zIndex':'60', 'display':'none', 'border-collapse': this.css('border-collapse'), 'border-spacing': this.css('border-spacing'), 'margin-left': this.css('margin-left'), 'width': this.css('width') }); //rewrite style cell of header $.each(this.find("thead>tr>th"), function(ind,val){ $(ClnH.find('tr>th')[ind]).css($(val).getStyleObject()); }); return ClnH;} $.fn.moveScroll=function(){ var offset = $(window).scrollTop(); if (offset > tableTop && offset<tableBottom){ if(ClnH.is(":hidden"))ClnH.show(); $("#fixH").css('margin-left',"-"+$(window).scrollLeft()+"px"); } else if (offset < tableTop || offset>tableBottom){ if(!ClnH.is(':hidden'))ClnH.hide(); } }; })( jQuery ); var $myfixedHeader = $("#repTb").FixedHeader(); $(window).scroll($myfixedHeader.moveScroll); 
 /* CSS - important only NOT transparent background */ #repTB{border-collapse: separate;border-spacing: 0;} #repTb thead,#fixH thead{background: #e0e0e0 linear-gradient(#d8d8d8 0%, #e0e0e0 25%, #e0e0e0 75%, #d8d8d8 100%) repeat scroll 0 0;border:1px solid #CCCCCC;} #repTb td{border:1px solid black} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <h3>example</h3> <table id="repTb"> <thead> <tr><th>Col1</th><th>Column2</th><th>Description</th></tr> </thead> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> <tr><td>info</td><td>info</td><td>info</td></tr> </table> 

这可以通过使用样式属性转换来实现。 你所要做的就是把你的表格换成固定高度和溢出设置为自动的div,例如:

 .tableWrapper { overflow: auto; height: calc( 100% - 10rem ); } 

然后,你可以附加onscroll处理程序,在这里你有方法,发现每个表用<div class="tableWrapper"></div>包装:

  fixTables () { document.querySelectorAll('.tableWrapper').forEach((tableWrapper) => { tableWrapper.addEventListener('scroll', () => { var translate = 'translate(0,' + tableWrapper.scrollTop + 'px)' tableWrapper.querySelector('thead').style.transform = translate }) }) } 

这里是工作的例子(我用bootstrap使它更漂亮): 小提琴

对于那些也想支持IE和Edge的人来说,这里是一个片段:

  fixTables () { const tableWrappers = document.querySelectorAll('.tableWrapper') for (let i = 0, len = tableWrappers.length; i < len; i++) { tableWrappers[i].addEventListener('scroll', () => { const translate = 'translate(0,' + tableWrappers[i].scrollTop + 'px)' const headers = tableWrappers[i].querySelectorAll('thead th') for (let i = 0, len = headers.length; i < len; i++) { headers[i].style.transform = translate } }) } } 

在IE和边缘滚动是有点滞后…但它的作品

这是帮助我找出答案的答案 : 答案

创建与主表相同标题的附加表。 只需将一行中的所有标题放入新表中即可。 确定绝对和背景白色。 对于主表把它放在一个div,并使用一些高度和溢出-y滚动。 这样我们的新表将克服主表的头,并留在那里。 围绕一切的一切。 下面是粗略的代码来做到这一点。

  <div class="col-sm-8"> <table id="header-fixed" class="table table-bordered table-hover" style="width: 351px;position: absolute;background: white;"> <thead> <tr> <th>Col1</th> <th>Col2</th> <th>Col3</th> </tr> </thead> </table> <div style="height: 300px;overflow-y: scroll;"> <table id="tableMain" class="table table-bordered table-hover" style="table-layout:fixed;overflow-wrap: break-word;cursor:pointer"> <thead> <tr> <th>Col1</th> <th>Col2</th> <th>Col3</th> </tr> </thead> <tbody> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> <tr> <td>info</td> <td>info</td> <td>info</td> </tr> </tbody> </table> </div> </div>