How can I lock the first row and first column of a table when scrolling, possibly using JavaScript and CSS?

后端 未结 13 2046
攒了一身酷
攒了一身酷 2020-11-27 03:11

How can I create a table that has its first row and first column both locked, as in Excel, when you activate \'freeze panes\'? I need the table to both scroll horizontally

相关标签:
13条回答
  • 2020-11-27 03:48

    Sort and Lock Table is the only solution I have seen which does work on other browsers than IE. (although this "locked column css" might do the trick as well). Required code block below.

    <!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 i.e. 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>
    
    0 讨论(0)
  • 2020-11-27 03:50

    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>&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>

    0 讨论(0)
  • 2020-11-27 03:50

    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.

    0 讨论(0)
  • 2020-11-27 03:55

    Here is one that I made that is pure javascript/css only.

    https://jsfiddle.net/KirbyLWallace/x5sbe0dk/5/

    It's meant to be used in full width screen, but I've modified to fit a specific width for the fiddle.

    <body onResize="scaleElements()">
    
    <div id="table-container-div">
    
    <table id="data-table">
      <thead id="th-header">
        <tr id="th-header-row">
          <td>Column1</td>
          <td>Column2</td>
          <td>Column3</td>
          <td>Column4</td>
        </tr>
      </thead>
    
      <tbody id="tbl-body">
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
        <tr><td>a</td><td>b</td><td>c</td><td>d</td></tr>
        <tr><td>1</td><td>2</td><td>3</td><td>4</td></tr>
        <tr><td>h</td><td>i</td><td>j</td><td>k</td></tr>
      </tbody>
    
    </table>
    

    javascript:

    (() => {
            scaleElements();  
        })();
    
    
      function scaleElements() {
    
            // element() is just shorthand for document.getElementById().
    
            // scaleElements() scales a number of other things, not included here, 
            // that get rescaled any time the browser, or a container is resized.
            // the table header row here is just one of them...
            //
            // this thing includes checks to see if a table with the table & thead 
            // is on the page.  If it is, it checks to see if the span container is
            // here (it's not on the first run, but it is on subsequent calls.  So, 
            // it adds it if it needs it, or reuses it if it's there.
    
            if (element("data-table")) {
    
                if (element("th-span-container")) {
                    element("th-span-container").parentElement.removeChild(element("th-span-container"));
                }
    
                var x = document.createElement("div");
                    x.id = "th-span-container";
                    x.style.cssFloat = "left";
                    x.style.position = "fixed";
                    x.style.top = "10px";
    
                    // you will want to fiddle with your own particular positioning. 
                    // this one is positioned to work on a table that is below a page 
                    // logo banner.
    
                var tds = element("th-header-row").getElementsByTagName("td");
    
                for (i = 0; i < tds.length; i++) {
    
                    let z = tds[i];
                    let y = document.createElement("span");
    
                    y.style.padding = "0px";
                    y.style.margin = "0px";
                    y.style.fontFamily = "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif";
                    y.style.fontSize = "13px";
                    y.style.border = "0px";
                    y.style.position = "absolute";
                    y.style.color = "white";
                    y.style.backgroundColor = "#3D6588";
                    y.style.left = z.offsetLeft + "px";
                    y.style.height = z.offsetHeight + "px";
                    y.style.lineHeight = z.offsetHeight + "px";
                    y.style.width = z.offsetWidth + "px";
                    y.innerHTML = z.innerHTML;
                    x.appendChild(y);
    
                }
    
                element("table-container-div").appendChild(x);
                element("th-header-row").style.visibility = "hidden";
    
            }
    
        }
    
    function element(e) {
        return document.getElementById(e);
    }
    

    css:

    body {
      background: black;
    }
    
    #table-container-div {
                width: 310px;
                position: absolute;
                top: 10px;
                bottom: 10px;
                overflow-x: hidden;
                overflow-y: auto;
                min-width: 320px;
            }
    
            table {
                font-size: 13px;
                height: 120px;
                width: 300px;
                border: 0px solid red;
                background-color: #11171F;
            }
    
            tr {
                height: 22px;
                color: #cff3ff;
            }
    
                tr:hover {
                    background-color: dimgrey;
                }
    
            td {
              color:white;
                border-right: 1px dotted #4F4F4F;
            }
    
            #th-header-row {
                background-color: #3D6588;
                color: white;
            }
    
    0 讨论(0)
  • 2020-11-27 03:57

    It's actually do-able without JavaScript, but using pure CSS + HTML with sticky position. Just add "position:sticky" to the cells you'd like to freeze.

    For building a table, you can either use or CSS grid, and this technique works on both of them.

    Here is an example formatting with table tag ( live demo here ):

    <table>
      <tr><th class="head"></th class="head"><th></th> ... </tr>
      <tr><th class="head"></th>             <th></th> ... </tr>
    ...
    </table>
    <style type="text/css">
      .head { position: sticky; top: 0; left: 0;}
    </style>
    

    And here is an example with CSS Grid ( live demo here ):

    <div class="grid">
       <!-- cells to freeze -->
       <div class="entry head"></div>
       <div class="entry head"></div>
       ...
       <!-- normal cells -->
       <div class="entry"></div>
       ...
    </div>
    <style type="text/css">
      .grid {
        display: grid;
        grid-template-columns: repeat(<your-cell-count>, <cell-size>); 
      } 
      .entry.head { position: sticky; top: 0; left: 0 }
    </style>
    

    You probably will need to take care of the cells frozen both horizontally and vertically ( e.g., setting a z-index larger than others ) but it will be still CSS thing.

    I think the main drawback of this approach is, probably, the browser compatibility issue. Check Can I Use CSS-sticky and Can I use CSS grid before using these techniques.

    0 讨论(0)
  • 2020-11-27 03:58

    How about a solution where you put the actual "data" of the table inside its own div, with overflow: scroll;? Then the browser will automatically create scrollbars for the portion of the "table" you do not want to lock, and you can put the "table header"/first row just above that <div>.

    Not sure how that would work with scrolling horizontally though.

    0 讨论(0)
提交回复
热议问题