How do I create an HTML table with a fixed/frozen left column and a scrollable body?

后端 未结 25 1530
有刺的猬
有刺的猬 2020-11-21 22:27

I need a simple solution. I know it\'s similar to some other questions, like:

  • HTML table with fixed headers and a fixed column?
  • How can I lock the fir
相关标签:
25条回答
  • 2020-11-21 23:02

    In case of fixed width left column the best solution is provided by Eamon Nerbonne.

    In case of variable width left column the best solution I found is to make two identical tables and push one above another. Demo: http://jsfiddle.net/xG5QH/6/.

    <!DOCTYPE html>
    <html>
    <head>
    <style type="text/css">
    /* important styles */
    
    .container {
       /* Attach fixed-th-table to this container,
          in order to layout fixed-th-table
          in the same way as scolled-td-table" */
       position: relative;
    
       /* Truncate fixed-th-table */
       overflow: hidden;
    }
    
    .fixed-th-table-wrapper td,
    .fixed-th-table-wrapper th,
    .scrolled-td-table-wrapper td,
    .scrolled-td-table-wrapper th {
       /* Set background to non-transparent color
          because two tables are one above another.
        */
       background: white;
    }
    .fixed-th-table-wrapper {
       /* Make table out of flow */
       position: absolute;
    }
    .fixed-th-table-wrapper th {
        /* Place fixed-th-table th-cells above 
           scrolled-td-table td-cells.
         */
        position: relative;
        z-index: 1;
    }
    .scrolled-td-table-wrapper td {
        /* Place scrolled-td-table td-cells
           above fixed-th-table.
         */
        position: relative;
    }
    .scrolled-td-table-wrapper {
       /* Make horizonal scrollbar if needed */
       overflow-x: auto;
    }
    
    
    /* Simulating border-collapse: collapse,
       because fixed-th-table borders
       are below ".scrolling-td-wrapper table" borders
    */
    
    table {
        border-spacing: 0;
    }
    td, th {
       border-style: solid;
       border-color: black;
       border-width: 1px 1px 0 0;
    }
    th:first-child {
       border-left-width: 1px;
    }
    tr:last-child td,
    tr:last-child th {
       border-bottom-width: 1px;
    }
    
    /* Unimportant styles */
    
    .container {
        width: 250px;
    }
    td, th {
       padding: 5px;
    }
    </style>
    </head>
    
    <body>
    <div class="container">
    
    <div class="fixed-th-table-wrapper">
    <!-- fixed-th-table -->
    <table>
        <tr>
             <th>aaaaaaa</th>
             <td>ccccccccccc asdsad asd as</td>
             <td>ccccccccccc asdsad asd as</td>
        </tr>
        <tr>
             <th>cccccccc</th>
             <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
             <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
        </tr>
    </table>
    </div>
    
    <div class="scrolled-td-table-wrapper">
    <!-- scrolled-td-table
         - same as fixed-th-table -->
    <table>
        <tr>
             <th>aaaaaaa</th>
             <td>ccccccccccc asdsad asd as</td>
             <td>ccccccccccc asdsad asd as</td>
        </tr>
        <tr>
             <th>cccccccc</th>
             <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
             <td>xxxxxxxxxxxxxxxxxxxx yyyyyyyyyyyyyy zzzzzzzzzzzzz</td>
        </tr>
    </table>
    </div>
    
    </div>
    </body>
    </html>
    
    0 讨论(0)
  • 2020-11-21 23:03

    A little late but I did run across this thread when trying out solutions for myself. Assuming you're using modern browsers nowadays, I came up with a solution using CSS calc() to help guarantee widths met up.

    .table-fixed-left table,
    .table-fixed-right table {
      border-collapse: collapse;
    }
    .table-fixed-right td,
    .table-fixed-right th,
    .table-fixed-left td,
    .table-fixed-left th {
      border: 1px solid #ffffd;
      padding: 5px 5px;
    }
    .table-fixed-left {
      width: 120px;
      float: left;
      position: fixed;
      overflow-x: scroll;
      white-space: nowrap;
      text-align: left;
      border: 1px solid #ffffd;
      z-index: 2;
    }
    .table-fixed-right {
      width: calc(100% - 145px);
      right: 15px;
      position: fixed;
      overflow-x: scroll;
      border: 1px solid #ffffd;
      white-space: nowrap;
    }
    .table-fixed-right td,
    .table-fixed-right th {
      padding: 5px 10px;
    }
    <div class="table-fixed-left">
      <table>
        <tr>
          <th>Normal Header</th>
        </tr>
        <tr>
          <th>Header with extra line
            <br/>&nbsp;</th>
        </tr>
        <tr>
          <th>Normal Header</th>
        </tr>
        <tr>
          <th>Normal with extra line
            <br/>&nbsp;</th>
        </tr>
        <tr>
          <th>Normal Header</th>
        </tr>
        <tr>
          <th>Normal Header</th>
        </tr>
      </table>
    </div>
    <div class="table-fixed-right">
      <table>
        <tr>
          <th>Header</th>
          <th>Another header</th>
          <th>Header</th>
          <th>Header really really really really long</th>
        </tr>
        <tr>
          <td>Info Long</td>
          <td>Info
            <br/>with second line</td>
          <td>Info
            <br/>with second line</td>
          <td>Info Long</td>
        </tr>
        <tr>
          <td>Info Long</td>
          <td>Info Long</td>
          <td>Info Long</td>
          <td>Info Long</td>
        </tr>
        <tr>
          <td>Info
            <br/>with second line</td>
          <td>Info
            <br/>with second line</td>
          <td>Info
            <br/>with second line</td>
          <td>Info</td>
        </tr>
        <tr>
          <td>Info</td>
          <td>Info</td>
          <td>Info</td>
          <td>Info</td>
        </tr>
        <tr>
          <td>Info</td>
          <td>Info</td>
          <td>Info</td>
          <td>Info</td>
        </tr>
      </table>
    </div>

    Hope this helps someone!

    0 讨论(0)
  • 2020-11-21 23:06

    If you're in Webdevelopper hell and need to make this work for IE6, here's a sample code I used:

    <html>
    <head>
    <style type="text/css">
    .fixme {
        position: relative;
        left: expression( ( 20 + ( ignoreMe2 = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft ) ) + 'px' );
        background-color: #FFFFFF;
    }
    </style>
    </head>
    <body>
    <table width="1500px" border="2">
        <tr>
            <td class="fixme" style="width: 200px;">loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet</td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
        </tr>
        <tr>
            <td class="fixme" style="width: 200px;">loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
        </tr>
        <tr>
            <td class="fixme" style="width: 200px;">loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
        </tr>
        <tr>
            <td class="fixme" style="width: 200px;">loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
            <td>loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet loremp ispum dolor sit amet </td>
        </tr>
    </table>
    </body>
    </html>
    

    This will work probably ONLY for IE6, so use conditional comments for the CSS.

    0 讨论(0)
  • 2020-11-21 23:06

    No need to add any plugin, CSS can do this job !!!

    The idea is to make the position of all the first cells in each column absolute, and make width fixed. Ex:

    max-width: 125px;
    min-width: 125px;
    position: absolute;
    

    This hides some parts of some columns under the first column, so add an empty second column (add second empty td) with width same as the first column.

    I tested and this works in Chrome and Firefox.

    0 讨论(0)
  • 2020-11-21 23:07

    You can just make the first column position: sticky; z-index: 9. It will make the column/row stick to its current position. Checkout my example codepen here https://codepen.io/swastikmishra/pen/zYYdKBQ

    HTML Example

    <style type="text/css">
                table{ text-align: center; }
                .table-container{ width: 500px; height: 300px; overflow: scroll;}
                table th, table td {
                    white-space: nowrap;
                    padding: 10px 20px;
                    font-family: Arial;
                }
                table tr th:first-child, table td:first-child{
                    position: sticky;
                    width: 100px;
                    left: 0;
                    z-index: 10;
                    background: #fff;
                }
                table tr th:first-child{
                    z-index: 11;
                }
                table tr th{
                    position: sticky;
                    top: 0;
                    z-index: 9;
                    background: #fff;
                }
            </style>
            <div class="table-container">
                <table>
                    <tr><th>Hello World</th><th>Hello World</th><th>Hello World</th><th>Hello World</th><th>Hello World</th><th>Hello World</th><th>Hello World</th></tr>
                    <tr><td>H11</td><td>H12</td><td>H13</td><td>H14</td><td>H15</td><td>H16</td><td>H17</td></tr>
                    <tr><td>H21</td><td>H22</td><td>H23</td><td>H24</td><td>H25</td><td>H26</td><td>H27</td></tr>
                    <tr><td>H31</td><td>H32</td><td>H33</td><td>H34</td><td>H35</td><td>H36</td><td>H37</td></tr>
                    <tr><td>H41</td><td>H42</td><td>H44</td><td>H44</td><td>H45</td><td>H46</td><td>H47</td></tr>
                    <tr><td>H51</td><td>H52</td><td>H54</td><td>H54</td><td>H55</td><td>H56</td><td>H57</td></tr>
                    <tr><td>H61</td><td>H62</td><td>H64</td><td>H64</td><td>H65</td><td>H66</td><td>H67</td></tr>
                    <tr><td>H71</td><td>H72</td><td>H74</td><td>H74</td><td>H75</td><td>H76</td><td>H77</td></tr>
                    <tr><td>H81</td><td>H82</td><td>H84</td><td>H84</td><td>H85</td><td>H86</td><td>H87</td></tr>
                </table>
            </div>
    
    0 讨论(0)
  • 2020-11-21 23:07

    In HTML5, you can use CSS style.transform.
    However, i reccomend you "swipe between pages" turn off If you implement on Mac.

    look at sample codePen

    let l  = 0;
    let t  = 0;
    
    const MouseWheelHandler = (e) => {
      // vertical scroll
      if (e.deltaX == -0) {
        // t = t - e.deltaY
    
      // horizonal scroll
      } else if (e.deltaY == -0) {
        l = l - e.deltaX
        if (l >= 0) {
          l = 0;
          document.getElementById("gantt_task").style.transform = "translateX(1px)"
          document.getElementById("gantt_task_header").style.transform = "translateX(1px)"
          return false
        } 
        document.getElementById("gantt_task").style.transform = "translateX(" + l.toString() + "px)"
        document.getElementById("gantt_task_header").style.transform = "translateX(" + l.toString() + "px)"
      }
      return false;
    }
    
    window.addEventListener("wheel", MouseWheelHandler, false);
    .row {
      border-bottom: 1px solid #979A9A
    }
    #gantt_grid_header {
      height:   30px;
      width:    100px;
      position: fixed;
      z-index:  3;
      top:      0px;
      left:     0px;
      border:   1px solid #cecece;
      background-color: #F08080;
    }     
    
    #gantt_task_header {
      height:   30px;
      width:    400px;
      position: fixed;
      z-index:  2;
      top:      0px;
      left:     100px;
      border:   1px solid #cecece;
      background-color: #FFC300;
    }
    
    #gantt_grid {
      width:    100px; 
      height:   400px;
      position: absolute;
      left:     0px;
      top:      0px;
      z-index:  1;
      border:   1px solid #cecece;
      background-color: #DAF7A6;
    }
    
    #gantt_task {
      width:    400px; 
      height:   400px;
      position: absolute;
      left:     100px;
      top:      0px;
      border:   1px solid #cecece;
      background-color: #FF5733;
    }
    <html>
        <div id="gantt_grid_header">
          HEADER
        </div>
        <div id="gantt_grid">
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
          <div class="row">V Scroll OK</div>
        </div>
        <div id="gantt_task_header">
          DATA HEADER
        </div>
        <div id="gantt_task">
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
          <div class="row">Vertical,Horizenal Scroll OK</div>
        </div>
    </html>

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