JSFiddle - React, Tailwind, and code Playground
by Ilmv
HTML
<div id="container">
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>Some Really Long String</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
...
CSS
#container {
height: 500px;
overflow-y: auto;
border: 1px solid red;
//position: relative;
}
table {
margin: 50px 0 5000px 0;
width: 75%;
}
td, th {
border: 1px solid #ccc;
padding: 2px;
}
th {
border-bottom: 2px solid orange;
}
thead tr {
background-color: white;
}
table.sticky-header thead {
position: relative;
width: 75%;
}
JavaScript
// *****
// NOTES
// the thead element loses it's width when set to absolute
// cannot even set as same width because th elements have no width
// might be dangerous explicitly setting widths on float event
// ^ especially with colspans etc
// possible to clone (1) the table, hide (2) the tbody + tfoot and
// display at the top? Leaving the existing thead to float on by.
// 1) Don't want to
$(document).ready(function() {
var table_margin_top = parseInt($('table').css('marginTop'));
$('#container').scroll(function() {
var $self = $(this),
$table = $self.find('table'),
$thead = $table.find('thead'),
offset = $table.position(),
container_position = $self.position();
console.log(offset.top + (container_position.top - table_margin_top));
// now we're not relative, include container position
if (offset.top + table_margin_top < 0 + container_position.top) {
$table.addClass('sticky-header');
// position doesn't include things like borders
// probably not padding either
$thead.css('top', parseInt(container_position.top));
$table.css('marginTop', table_margin_top + $thead.height());
} else {
$table.removeClass('sticky-header');
$table.css('marginTop', table_margin_top);
}
});
});