JSFiddle - React, Tailwind, and code Playground
HTML
<h2>Lorem Ipsum</h2>
<table id="bodyTable">
<tbody><tr><td id="bodyCell">
<div class="allow-overflow-x">
<table class="worksheet">
<thead>
<tr>
<th class="corner"><!-- Corner --></th>
<th class="column">Column</th>
<th class="column">Column</th>
<th class="column">Column</th>
<th class="column">Column</th>
<th class="column">Column</th>
<th class="column">Column</th>
<th class="column">Column</th>
<th class="column">Column</th>
</tr>
</thead>
<tbody>
<tr>
<th class="row">Row</th>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
</tr>
<tr>
<th class="row">Row</th>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
</tr>
<tr>
<th class="row">Row</th>
<td><input type="text" /></td>
...
CSS
table#bodyTable {
table-layout: fixed;
width:100%;
}
.worksheet th,
.worksheet td {
border-left: 1px solid black;
border-top: 1px solid black;
}
table.worksheet {
border-bottom: 1px solid black;
border-right: 1px solid black;
}
.worksheet th {
font-size: 96px;
}
.allow-overflow-x {
overflow-x: auto;
}
/* For visual clarification only in the fiddle */
body { background: darkgray; }
table#bodyTable { background: white; }
table.worksheet th.corner { background: red; color:white; }
table.worksheet th.column { background: darkgreen; color:white; }
table.worksheet th.row { background: purple; color: white; }
JavaScript
/*
* How can I make the row and column headers "sticky"?
*
* I'd like the headers to float, similarly to how frozen rows and columns
* work in Excel. But I want the headers to float within the confines of the
* div.allow-overflow-x element, not in the entire window.
*
* I'd like to avoid JavaScript if at all possible.
*/