How can I lock the first row and first column of a table when scrolling, possibly using JavaScript and CSS?
Oh well, I looked up for scrollable table with fixed column to understand the need of this specific requirement and your question was one of it with no close answers..
I answered this question Large dynamically sized html table with a fixed scroll row and fixed scroll column which inspired to showcase my work as a plugin https://github.com/meetselva/fixed-table-rows-cols
The plugin basically converts a well formatted HTML table to a scrollable table with fixed table header and columns.
The usage is as below,
$('#myTable').fxdHdrCol({ fixedCols : 3, /* 3 fixed columns */ width : "100%", /* set the width of the container (fixed or percentage)*/ height : 500 /* set the height of the container */});
You can check the demo and documentation here
I did this with a combination of:
- Using multiple tables
- Fixed-size cells
- jQuery's scrollTop and scrollLeft functions
Here's a jsfiddle example to demonstrate.
Haven't tested on all browsers but I imagine it's not great on older IE versions.
$("#clscroll-content").scroll(function() { $("#clscroll-row-headers").scrollTop($("#clscroll-content").scrollTop()); $("#clscroll-column-headers").scrollLeft($("#clscroll-content").scrollLeft());});$("#clscroll-column-headers").scroll(function() { $("#clscroll-content").scrollLeft($("#clscroll-column-headers").scrollLeft());});$("#clscroll-row-headers").scroll(function() { $("#clscroll-content").scrollTop($("#clscroll-row-headers").scrollTop());});
.clscroll table { table-layout: fixed;}.clscroll td, .clscroll th { overflow: hidden;}.corner-header { float: left;}.column-headers { float: left; overflow: scroll;}.row-headers { clear: both; float: left; overflow: scroll;}.table-content { table-layout: fixed; float: left; overflow: scroll;}.clscroll td, .clscroll th { width: 200px; border: 1px solid black;}.row-headers, .table-content { height: 100px;}.column-headers, .table-content, .table-content table, .column-headers table { width: 400px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="clscroll corner-header"> <table> <tr> <th> </th> </tr> </table></div><div class="clscroll column-headers" id="clscroll-column-headers"> <table> <tr> <th>Bus</th> <th>Plane</th> <th>Boat</th> <th>Bicycle</th> </tr> </table></div><div class="clscroll row-headers" id="clscroll-row-headers"> <table> <tr> <th>Red</th> </tr> <tr> <th>Green</th> </tr> <tr> <th>Blue</th> </tr> <tr> <th>Orange</th> </tr> <tr> <th>Purple</th> </tr> <tr> <th>Yellow</th> </tr> <tr> <th>Pink</th> </tr> <tr> <th>Brown</th> </tr> </table></div><div class="clscroll table-content" id="clscroll-content"> <table> <tr> <td>Red Bus</td> <td>Red Plane</td> <td>Red Boat</td> <td>Red Bicycle</td> </tr> <tr> <td>Green Bus</td> <td>Green Plane</td> <td>Green Boat</td> <td>Green Bicycle</td> </tr> <tr> <td>Blue Bus</td> <td>Blue Plane</td> <td>Blue Boat</td> <td>Blue Bicycle</td> </tr> <tr> <td>Orange Bus</td> <td>Orange Plane</td> <td>Orange Boat</td> <td>Orange Bicycle</td> </tr> <tr> <td>Purple Bus</td> <td>Purple Plane</td> <td>Purple Boat</td> <td>Purple Bicycle</td> </tr> <tr> <td>Yellow Bus</td> <td>Yellow Plane</td> <td>Yellow Boat</td> <td>Yellow Bicycle</td> </tr> <tr> <td>Pink Bus</td> <td>Pink Plane</td> <td>Pink Boat</td> <td>Pink Bicycle</td> </tr> <tr> <td>Brown Bus</td> <td>Brown Plane</td> <td>Brown Boat</td> <td>Brown Bicycle</td> </tr> </table></div>
You need two tables, where the first one is an exact overlay over the second one. The second one contains all the data, where the first one just contains the first column. You have to synchronize it's width and depending on the content also the height of it's rows.
Additional to this two tables, you need a third one. That's the first row, which lays exactly between the other two and has to be synchronized in the same way.
You will need absolute positioning here. Next, you would synchronize the scrolling of the data table with the scrolling positions of the head row and first column table.
That works very well in all major browsers, except for one issue: The synchronized scrolling will flutter. To fix that, you need two outher div containers that hold a clone of the content of the header row and the first column. When scrolling vertically, you display the header row clone to prevent fluttering, while you reposition the original in the background.When scrolling horizontally, you would show the first row clone. Same thing here.