I am trying to design an HTML table where the header will stay at the top of the page when AND ONLY when the user scrolls it out of view. For example, the table may be 500
In this solution fixed header is created dynamically, the content and style is cloned from THEAD
all you need is two lines for example:
var $myfixedHeader = $("#Ttodo").FixedHeader(); //create fixed header
$(window).scroll($myfixedHeader.moveScroll); //bind function to scroll event
My jquery plugin FixedHeader and getStyleObject provided below you can to put in the file .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(/\-([a-z])/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>
You would do something like this by tapping into the scroll
event handler on window
, and using another table
with a fixed position to show the header at the top of the page.
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();
}
});
This will show the table head when the user scrolls down far enough to hide the original table head. It will hide again when the user has scrolled the page up far enough again.
Working example: http://jsfiddle.net/andrewwhitaker/fj8wM/
I found a simple solution without using JQuery and using CSS only.
You have to put the fixed contents inside 'th' tags and add the CSS
table th {
position:sticky;
top:0;
z-index:1;
border-top:0;
background: #ededed;
}
The position, z-index and top properties are enough. But you can apply the rest to give for a better view.
This will help you to have a fixed header which can also be scrolled horizontally with data.
<!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> </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>
I found a solution without jquery
HTML
<table class="fixed_header">
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3</th>
<th>Col 4</th>
<th>Col 5</th>
</tr>
</thead>
<tbody>
<tr>
<td>row 1-0</td>
<td>row 1-1</td>
<td>row 1-2</td>
<td>row 1-3</td>
<td>row 1-4</td>
</tr>
<tr>
<td>row 2-0</td>
<td>row 2-1</td>
<td>row 2-2</td>
<td>row 2-3</td>
<td>row 2-4</td>
</tr>
<tr>
<td>row 3-0</td>
<td>row 3-1</td>
<td>row 3-2</td>
<td>row 3-3</td>
<td>row 3-4</td>
</tr>
<tr>
<td>row 4-0</td>
<td>row 4-1</td>
<td>row 4-2</td>
<td>row 4-3</td>
<td>row 4-4</td>
</tr>
<tr>
<td>row 5-0</td>
<td>row 5-1</td>
<td>row 5-2</td>
<td>row 5-3</td>
<td>row 5-4</td>
</tr>
<tr>
<td>row 6-0</td>
<td>row 6-1</td>
<td>row 6-2</td>
<td>row 6-3</td>
<td>row 6-4</td>
</tr>
<tr>
<td>row 7-0</td>
<td>row 7-1</td>
<td>row 7-2</td>
<td>row 7-3</td>
<td>row 7-4</td>
</tr>
</tbody>
</table>
CSS
.fixed_header{
width: 400px;
table-layout: fixed;
border-collapse: collapse;
}
.fixed_header tbody{
display:block;
width: 100%;
overflow: auto;
height: 100px;
}
.fixed_header thead tr {
display: block;
}
.fixed_header thead {
background: black;
color:#fff;
}
.fixed_header th, .fixed_header td {
padding: 5px;
text-align: left;
width: 200px;
}
You can see it working here: https://jsfiddle.net/lexsoul/fqbsty3h
Source: https://medium.com/@vembarrajan/html-css-tricks-scroll-able-table-body-tbody-d23182ae0fbc
Well, after reviewing all available solutions I wrote plugin which can freeze any row (not only th) at the top of page or container. It's very simple and very fast. Feel free to use it. http://maslianok.github.io/stickyRows/