For what it's worth:
There are a couple of answers here but I don't think they actually answer the question. They don't operate on table headers (thead
elements) or they use 3rd party libraries. There are some subtle issues with lifting a thead
out of the table - the largest of which is that the cells will collapse down if the header text is wider or narrower than the data in the tbody
.
Here is my solution that solves the problem without any libraries and working on table headers. It makes no assumptions about the styling of the table, or the size of the headers; everything is calculated. Only tested in Chrome per the requirements of the OP.
Script:
function initFloatingHeaders() {
var tables = document.querySelectorAll('table.float-header');
var i = tables.length;
while (i--) {
var table = tables[i];
var wrapper = document.createElement('div');
wrapper.className = 'floating-header';
var clone = table.cloneNode(true);
wrapper.appendChild(clone);
table.parentNode.insertBefore(wrapper, table);
var thead = table.querySelector('thead');
wrapper.style.width = thead.scrollWidth + 'px';
wrapper.style.height = thead.scrollHeight + 'px';
wrapper.style.left = table.offsetLeft + 'px';
}
window.addEventListener('scroll', function() {
var headers = document.querySelectorAll('div.floating-header');
var bodyHeight = document.body.offsetHeight;
var i = headers.length;
while (i--) {
var header = headers[i];
var tableBounds = header.nextSibling.getBoundingClientRect();
if (tableBounds.top < 0 && tableBounds.bottom > 0) {
header.style.display = 'block';
} else {
header.style.display = null;
}
}
}, false);
}
Tables should have the class float-header
applied and initFloatingHeaders
should be called on load or documentReady. Example: http://jsbin.com/ulusit/2 (Old example with bad transitions: http://jsbin.com/ulusit/)