如何在滚动时locking表格的第一行和第一列,可能使用JavaScript和CSS?

如何创build一个表的第一行和第一列都locking,如在Excel中,当你激活“冻结窗格”? 我需要表格既水平和垂直滚动(有很多解决scheme,但只允许垂直滚动)。

所以,当你在表格中向下滚动时,第一行将保持放置,因为它将具有列标题。 这可能最终会成为一个thead ,或者可能不会,无论如何,使解决scheme更容易。

向右滚动时,第一列保持放置状态,因为它包含行的标签。

我相当肯定这是不可能的CSS,但任何人都可以指向我的JavaScript解决scheme? 它需要在所有主stream浏览器中运行。

哦,我查了固定列的滚动表了解这个特定需求的需要,你的问题是其中一个没有密切的答案..

我回答了这个问题大的dynamic大小的HTML表,固定的滚动行和固定的滚动列 ,这启发展示我的工作作为插件https://github.com/meetselva/fixed-table-rows-cols

该插件基本上将格式良好的HTML表格转换为具有固定表格标题和列的可滚动表格。

用法如下,

 $('#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 */ }); 

您可以在这里查看演示和文档

我已经发布我的jQuery插件解决scheme在这里: 冻结表头内滚动div

它确实是你想要的,而且非常轻巧,易于使用。

你需要两张表,第一张是第二张。 第二个包含所有的数据,其中第一个只包含第一列。 你必须同步它的宽度,并根据内容也是行的高度。

除了这两张表之外,还需要第三张。 这是第一行,它恰好在另外两行之间,并且必须以相同的方式同步。

你需要绝对的定位。 接下来,您将使数据表的滚动与头行和第一列表的滚动位置同步。

这在所有主stream浏览器中都能很好地工作,除了一个问题:同步滚动会抖动。 为了解决这个问题,你需要两个outher div容器来保存标题行和第一列的内容。 当垂直滚动时,显示标题行克隆以防止飘动,而您将原件重新放置在背景中。 当水平滚动时,你会显示第一行的克隆。 这里一样的东西。

我是这样做的:

  • 使用多个表
  • 固定大小的单元格
  • jQuery的scrollTop和scrollLeft函数

这是一个jsfiddle示例来演示。

没有在所有的浏览器上testing过,但我想在旧的IE版本上不是很好。

 $("#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>&nbsp;</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> 

今天有很多跨浏览器的解决scheme,其中SuperTable是我喜欢的,因为它的优雅和简洁(现在正在继续使用MooGrid), SlickGrid带有一系列function。

这里有一个插件JQuery: https : //github.com/nitsugario/jQuery-Freeze-Table-Column-and-Rows

这是一个jQuery插件,可以使表行和列不滚动。 它可以获取给定的HTML表格对象,并将其设置为可冻结给定数量的列或行或两者,因此固定列或行不滚动。 被冻结的行应放置在表头部分。 它也可以结合使用colspan或rowspan属性来冻结行和列。

你必须testing它,但是如果你在页面中embedded了一个iframe,那么使用CSS将第一行和第一列绝对定位在iframe页面的0,0处,这将解决你的问题?

如何解决你把表的实际“数据”在自己的div, overflow: scroll; ? 然后,浏览器将自动为不想locking的“表格”部分创build滚动条,并且可以将“表格标题”/第一行放在<div>之上。

不知道如何这将水平滚动虽然。

sorting和locking表是唯一的解决scheme,我已经看到哪些工作在其他浏览器比IE浏览器。 (尽pipe这个“ locking列的CSS ”也可能会这样做)。 下面的代码块。

 <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="robots" content="noindex, nofollow"> <meta name="googlebot" content="noindex, nofollow"> <script type="text/javascript" src="/js/lib/dummy.js"></script> <link rel="stylesheet" type="text/css" href="/css/result-light.css"> <style type="text/css"> /* Scrollable Content Height */ .scrollContent { height:100px; overflow-x:hidden; overflow-y:auto; } .scrollContent tr { height: auto; white-space: nowrap; } /* Prevent Mozilla scrollbar from hiding right-most cell content */ .scrollContent tr td:last-child { padding-right: 20px; } /* Fixed Header Height */ .fixedHeader tr { position: relative; height: auto; } /* Put border around entire table */ div.TableContainer { border: 1px solid #7DA87D; } /* Table Header formatting */ .headerFormat { background-color: white; color: #FFFFFF; margin: 3px; padding: 1px; white-space: nowrap; font-family: Helvetica; font-size: 16px; text-decoration: none; font-weight: bold; } .headerFormat tr td { border: 1px solid #000000; background-color: #7DA87D; } /* Table Body (Scrollable Content) formatting */ .bodyFormat tr td { color: #000000; margin: 3px; padding: 1px; border: 0px none; font-family: Helvetica; font-size: 12px; } /* Use to set different color for alternating rows */ .alternateRow { background-color: #E0F1E0; } /* Styles used for SORTING */ .point { cursor:pointer; } td.sortedColumn { background-color: #E0F1E0; } tr.alternateRow td.sortedColumn { background-color: #c5e5c5; } .total { background-color: #FED362; color: #000000; white-space: nowrap; font-size: 12px; text-decoration: none; } </style> <title></title> <script type='text/javascript'>//<![CDATA[ /* This script and many more are available free online at The JavaScript Source :: http://www.javascriptsource.com Created by: Stan Slaughter :: http://www.stansight.com/ */ /* ====================================================== Generic Table Sort Basic Concept: A table can be sorted by clicking on the title of any column in the table, toggling between ascending and descending sorts. Assumptions: * The first row of the table contains column titles that are "clicked" to sort the table * The images 'desc.gif','asc.gif','none.gif','sorting.gif' exist * The img tag is in each column of the the title row to represent the sort graphic. * The CSS classes 'alternateRow' and 'sortedColumn' exist so we can have alternating colors for each row and a highlight the sorted column. Something like the <style> definition below, but with the background colors set to whatever you want. <style> tr.alternateRow { background-color: #E0F1E0; } td.sortedColumn { background-color: #E0F1E0; } tr.alternateRow td.sortedColumn { background-color: #c5e5c5; } </style> ====================================================== */ function sortTable(td_element,ignoreLastLines) { // If the optional ignoreLastLines parameter (number of lines *not* to sort at end of table) // was not passed then make it 0 ignoreLastLines = (typeof(ignoreLastLines)=='undefined') ? 0 : ignoreLastLines; var sortImages =['data:image/gif;base64,R0lGODlhCgAKAMQXAJOkk3mReXume3uTe3mieXGPcXOYc/Hx8Xadds/Wz9vg24ejh3GUcYOgg6a0pnGVcfP18+3w7c3TzdPY06u4q/r8+v///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABcALAAAAAAKAAoAAAUz4IVcZDleixQIQjA1pFFZx2FVRklZvOWUl8LsVgBeFLyE8TLgDZYESISwvAAA1QvjAQwBADs=','data:image/gif;base64,R0lGODlhCgAKAMQXAJOkk3mReXume3uTe3mieXGPcXOYc/Hx8Xadds/Wz9vg24ejh3GUcYOgg6a0pnGVcfP18+3w7c3TzdPY06u4q/r8+v///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABcALAAAAAAKAAoAAAUw4CVeDzOeFwCgIhFBBDtY1sAmtIIWFV0VJweNRhkZeoeDpWIQNSYBgSAgWYgQLGwIADs=','data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7','http://web.archive.org/web/20150906203819im_/http://www.javascriptsource.com/miscellaneous/sorting.gif']; // Get the image used in the first row of the current column var sortColImage = td_element.getElementsByTagName('img')[0]; // If current image is 'asc.gif' or 'none.gif' (elements 1 and 2 of sortImages array) then this will // be a descending sort else it will be ascending - get new sort image icon and set sort order flag var sortAscending = false; var newSortColImage = ""; if (sortColImage.getAttribute('src').indexOf(sortImages[1])>-1 || sortColImage.getAttribute('src').indexOf(sortImages[2])>-1) { newSortColImage = sortImages[0]; sortAscending = false; } else { newSortColImage = sortImages[1]; sortAscending = true; } // Assign "SORTING" image icon (element 3 of sortImages array)) to current column title // (will replace with newSortColImage when sort completes) sortColImage.setAttribute('src',sortImages[3]); // Find which column was clicked by getting it's column position var indexCol = td_element.cellIndex; // Get the table element from the td element that was passed as a parameter to this function var table_element = td_element.parentNode; while (table_element.nodeName != "TABLE") { table_element = table_element.parentNode; } // Get all "tr" elements from the table and assign then to the Array "tr_elements" var tr_elements = table_element.getElementsByTagName('tr'); // Get all the images used in the first row then set them to 'none.gif' // (element 2 or sortImages array) except for the current column (all ready been changed) var allImg = tr_elements[0].getElementsByTagName('img'); for(var i=0;i<allImg.length;i++){ if(allImg[i]!=sortColImage){allImg[i].setAttribute('src',sortImages[2])} } // Some explantion of the basic concept of the following code before we // actually start. Essentially we are going to copy the current columns information // into an array to be sorted. We'll sort the column array then go back and use the information // we saved about the original row positions to re-order the entire table. // We are never really sorting more than a columns worth of data, which should keep the sorting fast. // Create a new array for holding row information var clonedRows = new Array() // Create a new array to store just the selected column values, not the whole row var originalCol = new Array(); // Now loop through all the data row elements // NOTE: Starting at row 1 because row 0 contains the column titles for (var i=1; i<tr_elements.length - ignoreLastLines; i++) { // "Clone" the tr element ie save a copy all of its attributes and values clonedRows[i]=tr_elements[i].cloneNode(true); // Text value of the selected column on this row var valueCol = getTextValue(tr_elements[i].cells[indexCol]); // Format text value for sorting depending on its type, ie Date, Currency, number, etc.. valueCol = FormatForType(valueCol); // Assign the column value AND the row number it was originally on in the table originalCol[i]=[valueCol,tr_elements[i].rowIndex]; } // Get rid of element "0" from this array. A value was never assigned to it because the first row // in the table just contained the column titles, which we did not bother to assign. originalCol.shift(); // Sort the column array returning the value of a sort into a new array sortCol = originalCol.sort(sortCompare); // If it was supposed to be an Ascending sort then reverse the order if (sortAscending) { sortCol.reverse(); } // Now take the values from the sorted column array and use that information to re-arrange // the order of the tr_elements in the table for (var i=1; i < tr_elements.length - ignoreLastLines; i++) { var old_row = sortCol[i-1][1]; var new_row = i; tr_elements[i].parentNode.replaceChild(clonedRows[old_row],tr_elements[new_row]); } // Format the table, making the rows alternating colors and highlight the sorted column makePretty(table_element,indexCol,ignoreLastLines); // Assign correct sort image icon to current column title sortColImage.setAttribute('src',newSortColImage); } // Function used by the sort routine to compare the current value in the array with the next one function sortCompare (currValue, nextValue) { // Since the elements of this array are actually arrays themselves, just sort // on the first element which contiains the value, not the second which contains // the original row position if ( currValue[0] == nextValue[0] ) return 0; if ( currValue[0] < nextValue[0] ) return -1; if ( currValue[0] > nextValue[0] ) return 1; } //----------------------------------------------------------------------------- // Functions to get and compare values during a sort. //----------------------------------------------------------------------------- // This code is necessary for browsers that don't reflect the DOM constants // (like IE). if (document.ELEMENT_NODE == null) { document.ELEMENT_NODE = 1; document.TEXT_NODE = 3; } function getTextValue(el) { var i; var s; // Find and concatenate the values of all text nodes contained within the // element. s = ""; for (i = 0; i < el.childNodes.length; i++) if (el.childNodes[i].nodeType == document.TEXT_NODE) s += el.childNodes[i].nodeValue; else if (el.childNodes[i].nodeType == document.ELEMENT_NODE && el.childNodes[i].tagName == "BR") s += " "; else // Use recursion to get text within sub-elements. s += getTextValue(el.childNodes[i]); return normalizeString(s); } // Regular expressions for normalizing white space. var whtSpEnds = new RegExp("^\\s*|\\s*$", "g"); var whtSpMult = new RegExp("\\s\\s+", "g"); function normalizeString(s) { s = s.replace(whtSpMult, " "); // Collapse any multiple whites space. s = s.replace(whtSpEnds, ""); // Remove leading or trailing white space. return s; } // Function used to modify values to make then sortable depending on the type of information function FormatForType(itm) { var sortValue = itm.toLowerCase(); // If the item matches a date pattern (MM/DD/YYYY or MM/DD/YY or M/DD/YYYY) if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/) || itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/) || itm.match(/^\d[\/-]\d\d[\/-]\d\d\d\d$/) ) { // Convert date to YYYYMMDD format for sort comparison purposes // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX var yr = -1; if (itm.length == 10) { sortValue = itm.substr(6,4)+itm.substr(0,2)+itm.substr(3,2); } else if (itm.length == 9) { sortValue = itm.substr(5,4)+"0" + itm.substr(0,1)+itm.substr(2,2); } else { yr = itm.substr(6,2); if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; } sortValue = yr+itm.substr(3,2)+itm.substr(0,2); } } // If the item matches a Percent patten (contains a percent sign) if (itm.match(/%/)) { // Replace anything that is not part of a number (decimal pt, neg sign, or 0 through 9) with an empty string. sortValue = itm.replace(/[^0-9.-]/g,''); sortValue = parseFloat(sortValue); } // If item starts with a "(" and ends with a ")" then remove them and put a negative sign in front if (itm.substr(0,1) == "(" & itm.substr(itm.length - 1,1) == ")") { itm = "-" + itm.substr(1,itm.length - 2); } // If the item matches a currency pattern (starts with a dollar or negative dollar sign) if (itm.match(/^[£$]|(^-)/)) { // Replace anything that is not part of a number (decimal pt, neg sign, or 0 through 9) with an empty string. sortValue = itm.replace(/[^0-9.-]/g,''); if (isNaN(sortValue)) { sortValue = 0; } else { sortValue = parseFloat(sortValue); } } // If the item matches a numeric pattern if (itm.match(/(\d*,\d*$)|(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/)) { // Replace anything that is not part of a number (decimal pt, neg sign, or 0 through 9) with an empty string. sortValue = itm.replace(/[^0-9.-]/g,''); // sortValue = sortValue.replace(/,/g,''); if (isNaN(sortValue)) { sortValue = 0; } else { sortValue = parseFloat(sortValue); } } return sortValue; } //----------------------------------------------------------------------------- // Functions to update the table appearance after a sort. //----------------------------------------------------------------------------- // Style class names. var rowClsNm = "alternateRow"; var colClsNm = "sortedColumn"; // Regular expressions for setting class names. var rowTest = new RegExp(rowClsNm, "gi"); var colTest = new RegExp(colClsNm, "gi"); function makePretty(tblEl, col, ignoreLastLines) { var i, j; var rowEl, cellEl; // Set style classes on each row to alternate their appearance. for (i = 1; i < tblEl.rows.length - ignoreLastLines; i++) { rowEl = tblEl.rows[i]; rowEl.className = rowEl.className.replace(rowTest, ""); if (i % 2 != 0) rowEl.className += " " + rowClsNm; rowEl.className = normalizeString(rowEl.className); // Set style classes on each column (other than the name column) to // highlight the one that was sorted. for (j = 0; j < tblEl.rows[i].cells.length; j++) { cellEl = rowEl.cells[j]; cellEl.className = cellEl.className.replace(colTest, ""); if (j == col) cellEl.className += " " + colClsNm; cellEl.className = normalizeString(cellEl.className); } } } // END Generic Table sort. // ================================================= // Function to scroll to top before sorting to fix an IE bug // Which repositions the header off the top of the screen // if you try to sort while scrolled to bottom. function GoTop() { document.getElementById('TableContainer').scrollTop = 0; } //]]> </script> </head> <body> <table cellpadding="0" cellspacing="0" border="0"> <tr><td> <div id="TableContainer" class="TableContainer" style="height:230px;"> <table class="scrollTable"> <thead class="fixedHeader headerFormat"> <tr> <td class="point" onclick="GoTop(); sortTable(this,1);" title="Sort"><b>NAME</b> <img src="data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7" border="0"></td> <td class="point" onclick="GoTop(); sortTable(this,1);" title="Sort" align="right"><b>Amt</b> <img src="data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7" border="0"></td> <td class="point" onclick="GoTop(); sortTable(this,1);" title="Sort" align="right"><b>Lvl</b> <img src="data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7" border="0"></td> <td class="point" onclick="GoTop(); sortTable(this,1);" title="Sort" align="right"><b>Rank</b> <img src="data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7" border="0"></td> <td class="point" onclick="GoTop(); sortTable(this,1);" title="Sort" align="right"><b>Position</b> <img src="data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7" border="0"></td> <td class="point" onclick="GoTop(); sortTable(this,1);" title="Sort" align="right"><b>Date</b> <img src="data:image/gif;base64,R0lGODlhCgAKALMLAHaRdnCTcHegd7C8sNTa1Ku4q9vg24GXgfr8+uDl4P///////wAAAAAAAAAAAAAAACH5BAEAAAsALAAAAAAKAAoAAAQfcMlJq12hIHKoSEqIdBIQnslknkoqfedIBQNikFduRQA7" border="0"></td> </tr> </thead> <tbody class="scrollContent bodyFormat" style="height:200px;"> <tr class="alternateRow"> <td>Maha</td> <td align="right">$19,923.19</td> <td align="right">100</td> <td align="right">100</td> <td>Owner</td> <td align="right">01/02/2001</td> </tr> <tr> <td>Thrawl</td> <td align="right">$9,550</td> <td align="right">159</td> <td align="right">100%</td> <td>Co-Owner</td> <td align="right">11/07/2003</td> </tr> <tr class="alternateRow"> <td>Marhanen</td> <td align="right">$223.04</td> <td align="right">83</td> <td align="right">99%</td> <td>Banker</td> <td align="right">06/27/2006</td> </tr> <tr> <td>Peter</td> <td align="right">$121</td> <td align="right">567</td> <td align="right">23423%</td> <td>FishHead</td> <td align="right">06/06/2006</td> </tr> <tr class="alternateRow"> <td>Jones</td> <td align="right">$15</td> <td align="right">11</td> <td align="right">15%</td> <td>Bubba</td> <td align="right">10/27/2005</td> </tr> <tr> <td>Supa-De-Dupa</td> <td align="right">$145</td> <td align="right">91</td> <td align="right">32%</td> <td>momma</td> <td align="right">12/15/1996</td> </tr> <tr class="alternateRow"> <td>ClickClock</td> <td align="right">$1,213</td> <td align="right">23</td> <td align="right">1%</td> <td>Dada</td> <td align="right">1/30/1998</td> </tr> <tr> <td>Mrs. Robinson</td> <td align="right">$99</td> <td align="right">99</td> <td align="right">99%</td> <td>Wife</td> <td align="right">07/04/1963</td> </tr> <tr class="alternateRow"> <td>Maha</td> <td align="right">$19,923.19</td> <td align="right">100</td> <td align="right">100%</td> <td>Owner</td> <td align="right">01/02/2001</td> </tr> <tr> <td>Thrawl</td> <td align="right">$9,550</td> <td align="right">159</td> <td align="right">100%</td> <td>Co-Owner</td> <td align="right">11/07/2003</td> </tr> <tr class="alternateRow"> <td>Marhanen</td> <td align="right">$223.04</td> <td align="right">83</td> <td align="right">59%</td> <td>Banker</td> <td align="right">06/27/2006</td> </tr> <tr> <td>Peter</td> <td align="right">$121</td> <td align="right">567</td> <td align="right">534.23%</td> <td>FishHead</td> <td align="right">06/06/2006</td> </tr> <tr class="alternateRow"> <td>Jones</td> <td align="right">$15</td> <td align="right">11</td> <td align="right">15%</td> <td>Bubba</td> <td align="right">10/27/2005</td> </tr> <tr> <td>Supa-De-Dupa</td> <td align="right">$145</td> <td align="right">91</td> <td align="right">42%</td> <td>momma</td> <td align="right">12/15/1996</td> </tr> <tr class="alternateRow"> <td>ClickClock</td> <td align="right">$1,213</td> <td align="right">23</td> <td align="right">2%</td> <td>Dada</td> <td align="right">1/30/1998</td> </tr> <tr> <td>Mrs. Robinson</td> <td align="right">$99</td> <td align="right">99</td> <td align="right">(-10.42%)</td> <td>Wife</td> <td align="right">07/04/1963</td> </tr> <tr class="alternateRow"> <td>Maha</td> <td align="right">-$19,923.19</td> <td align="right">100</td> <td align="right">(-10.01%)</td> <td>Owner</td> <td align="right">01/02/2001</td> </tr> <tr> <td>Thrawl</td> <td align="right">$9,550</td> <td align="right">159</td> <td align="right">-10.20%</td> <td>Co-Owner</td> <td align="right">11/07/2003</td> </tr> <tr class="total"> <td><strong>TOTAL</strong>:</td> <td align="right"><strong>999999</strong></td> <td align="right"><strong>9999999</strong></td> <td align="right"><strong>99</strong></td> <td > </td> <td align="right"> </td> </tr> </tbody> </table> </div> </td></tr> </table> </body> </html> 

I ran across a site a few weeks back. This is a working example of the first column locked but it is not browser compatible with Firefox. I didn't do a lot of checking around but it seems it only works in IE. There are some notes the author provided along with it that you can read.

Lock the First column: http://home.tampabay.rr.com/bmerkey/examples/locked-column-csv.html

Let me know if you need the Javascript to lock the Table headers too.

You can do it, without javascript

see this link: http://yonax73.blogspot.com/2014/09/tabla-con-cabecera-estatica-cuerpo-con.html

or live demo: http://jsfiddle.net/yonatanalexis22/aeeme8mt/7/

 table{ border-spacing: 0; display: flex;/*Se ajuste dinamicamente al tamano del dispositivo**/ max-height: 40vh; /*El alto que necesitemos**/ overflow-y: auto; /**El scroll verticalmente cuando sea necesario*/ overflow-x: hidden;/*Sin scroll horizontal*/ table-layout: fixed;/**Forzamos a que las filas tenga el mismo ancho**/ width: 98vw; /*El ancho que necesitemos*/ border:1px solid gray;}