Fixed header table with horizontal scrollbar and vertical scrollbar on

146,037

Solution 1

This is not an easy one. I've come up with a Script solution. (I don't think this can be done using pure CSS)

the HTML stays the same as you posted, the CSS changes a little bit, JQuery code added.

Working Fiddle Tested on: IE10, IE9, IE8, FF, Chrome

BTW: if you have unique elements, why don't you use id's instead of classes? I think it gives a better selector performance.

Explanation of how it works: inner-container will span the entire space of the outer-container (so basically, he's not needed) but I left him there, so you wont need to change you DOM.

the table-header is relatively positioned, without a scroll (overflow: hidden), we will handle his scroll later.

the table-body have to span the rest of the inner-container height, so I used a script to determine what height to fix him. (it changes dynamically when you re-size the window) without a fixed height, the scroll wont appear, because the div will just grow large instead.. notice that this part can be done without script, if you fix the header height and use CSS3 (as shown in the end of the answer)

now it's just a matter of moving the header along with the body each time we scroll. this is done by a function assigned to the scroll event.

CSS (some of it was copied from your style)

*
{
    padding: 0;
    margin: 0;
}

body
{
    height: 100%;
    width: 100%;
}
table
{
    border-collapse: collapse; /* make simple 1px lines borders if border defined */
}
.outer-container
{
    background-color: #ccc;
    position: absolute;
    top:0;
    left: 0;
    right: 300px;
    bottom: 40px;
}

.inner-container
{
    height: 100%;
    overflow: hidden;
}

.table-header
{
    position: relative;
}
.table-body
{
    overflow: auto;
}

.header-cell
{
    background-color: yellow;
    text-align: left;
    height: 40px;
}
.body-cell 
{
    background-color: blue;
    text-align: left;
}
.col1, .col3, .col4, .col5
{
    width:120px;
    min-width: 120px;
}
.col2
{
    min-width: 300px;
}

JQuery

$(document).ready(function () {
    setTableBody();
    $(window).resize(setTableBody);
    $(".table-body").scroll(function ()
    {
        $(".table-header").offset({ left: -1*this.scrollLeft });
    });
});

function setTableBody()
{
    $(".table-body").height($(".inner-container").height() - $(".table-header").height());
}

If you don't care about fixing the header height (I saw that you fixed the cell's height in your CSS), some of the Script can be skiped if you use CSS3 :Shorter Fiddle (this will not work on IE8)

Solution 2

Here's a solution which again is not a CSS only solution. It is similar to avrahamcool's solution in that it uses a few lines of jQuery, but instead of changing heights and moving the header along, all it does is changing the width of tbody based on how far its parent table is scrolled along to the right.

An added bonus with this solution is that it works with a semantically valid HTML table.

It works great on all recent browser versions (IE10, Chrome, FF) and that's it, the scrolling functionality breaks on older versions.

But then the fact that you are using a semantically valid HTML table will save the day and ensure the table is still displayed properly, it's only the scrolling functionality that won't work on older browsers.

Here's a jsFiddle for demonstration purposes.

CSS

table {
    width: 300px;
    overflow-x: scroll;
    display: block;
}
thead, tbody {
    display: block;
}
tbody {
    overflow-y: scroll;
    overflow-x: hidden;
    height: 140px;
}
td, th {
    min-width: 100px;
}

JS

$("table").on("scroll", function () {
    $("table > *").width($("table").width() + $("table").scrollLeft());
});

I needed a version which degrades nicely in IE9 (no scrolling, just a normal table). Posting the fiddle here as it is an improved version. All you need to do is set a height on the tr.

Additional CSS to make this solution degrade nicely in IE9

tr {
    height: 25px; /* This could be any value, it just needs to be set. */ 
}

Here's a jsFiddle demonstrating the nicely degrading in IE9 version of this solution.

Edit: Updated fiddle links to link to a version of the fiddle which contains fixes for issues mentioned in the comments. Just adding a snippet with the latest and greatest version while I'm at it:

$('table').on('scroll', function() {
  $("table > *").width($("table").width() + $("table").scrollLeft());
});
html {
  font-family: verdana;
  font-size: 10pt;
  line-height: 25px;
}

table {
  border-collapse: collapse;
  width: 300px;
  overflow-x: scroll;
  display: block;
}

thead {
  background-color: #EFEFEF;
}

thead,
tbody {
  display: block;
}

tbody {
  overflow-y: scroll;
  overflow-x: hidden;
  height: 140px;
}

td,
th {
  min-width: 100px;
  height: 25px;
  border: dashed 1px lightblue;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <thead>
    <tr>
      <th>Column 1</th>
      <th>Column 2</th>
      <th>Column 3</th>
      <th>Column 4</th>
      <th>Column 5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>AAAAAAAAAAAAAAAAAAAAAAAAAA</td>
      <td>Row 1</td>
      <td>Row 1</td>
      <td>Row 1</td>
      <td>Row 1</td>
    </tr>
    <tr>
      <td>Row 2</td>
      <td>Row 2</td>
      <td>Row 2</td>
      <td>Row 2</td>
      <td>Row 2</td>
    </tr>
    <tr>
      <td>Row 3</td>
      <td>Row 3</td>
      <td>Row 3</td>
      <td>Row 3</td>
      <td>Row 3</td>
    </tr>
    <tr>
      <td>Row 4</td>
      <td>Row 4</td>
      <td>Row 4</td>
      <td>Row 4</td>
      <td>Row 4</td>
    </tr>
    <tr>
      <td>Row 5</td>
      <td>Row 5</td>
      <td>Row 5</td>
      <td>Row 5</td>
      <td>Row 5</td>
    </tr>
    <tr>
      <td>Row 6</td>
      <td>Row 6</td>
      <td>Row 6</td>
      <td>Row 6</td>
      <td>Row 6</td>
    </tr>
    <tr>
      <td>Row 7</td>
      <td>Row 7</td>
      <td>Row 7</td>
      <td>Row 7</td>
      <td>Row 7</td>
    </tr>
    <tr>
      <td>Row 8</td>
      <td>Row 8</td>
      <td>Row 8</td>
      <td>Row 8</td>
      <td>Row 8</td>
    </tr>
    <tr>
      <td>Row 9</td>
      <td>Row 9</td>
      <td>Row 9</td>
      <td>Row 9</td>
      <td>Row 9</td>
    </tr>
    <tr>
      <td>Row 10</td>
      <td>Row 10</td>
      <td>Row 10</td>
      <td>Row 10</td>
      <td>Row 10</td>
    </tr>
  </tbody>
</table>

Solution 3

Here is a HTML / CSS only solution (with a little javascript).

Apology to answer the question after this long, but the solution given did not suit me and I found a better one. Here is the easiest way to do it with HTML (no jquery):

Before that, the solution fiddle to the question. https://jsfiddle.net/3vzrunkt/

<div>
    <div style="overflow:hidden;;margin-right:16px" id="headerdiv">
        <table id="headertable" style="min-width:900px" border=1>
            <thead>
                <tr>
                    <th style="width:120px;min-width:120px;">One</th>
                    <th style="width:420px;min-width:420px;">Two</th>
                    <th style="width:120px;min-width:120px;">Three</th>
                    <th style="width:120px;min-width:120px;">Four</th>
                    <th style="width:120px;min-width:120px;">Five</th>
                </tr>
            </thead>
        </table>
    </div>

    <div style="overflow-y:scroll;max-height:200px;" 
         onscroll="document.getElementById('headerdiv').scrollLeft = this.scrollLeft;">
        <table id="bodytable" border=1 style="min-width:900px; border:1px solid">
            <tbody>
                <tr>
                    <td style="width:120px;min-width:120px;">body row1</td>
                    <td style="width:420px;min-width:420px;">body row2</td>
                    <td style="width:120px;min-width:120px;">body row2</td>
                    <td style="width:120px;min-width:120px;">body row2</td>
                    <td style="width:120px;min-width:120px;">body row2 en nog meer</td>
                </tr>
                :
                :
                :
                :

            </tbody>
        </table>
    </div>
</div>

And to explain the solution:

  1. you need and enclosing div no overflow/scroll required

  2. a header div containing the header table with overflow:hidden to ensure that the scrollbar is not displayed. Add margin-right:16px to ensure that the scrollbar is left outside it while synching.

  3. another div for containing the table records and overflow-y:scroll. Note the padding is required to get the scrollbar move right of the header.

  4. And the most important thing the magical js to sync the header and table data:

     onscroll="document.getElementById('headerdiv').scrollLeft = this.scrollLeft;"
    

Solution 4

This has been driving me crazy for literally weeks. I found a solution that will work for me that includes:

  1. Non-fixed column widths - they shrink and grow on window resizing.
  2. Table has a horizontal scroll-bar when needed, but not when it isn't.
  3. Number of columns is irrelevant - it will size to however many columns you need it to.
  4. Not all columns need to be the same width.
  5. Header goes all the way to the end of the right scrollbar.
  6. No javascript!

...but there are a couple of caveats:

  1. The vertical scrollbar is not visible until you scroll all the way to the right. Given that most people have scroll wheels, this was an acceptable sacrifice.

  2. The width of the scrollbar must be known. On my website I set the scrollbar widths (I'm not overly concerned with older, incompatible browsers), so I can then calculate div and table widths that adjust based on the scrollbar.

Instead of posting my code here, I'll post a link to the jsFiddle.

Fixed header table + scroll left/right.

Solution 5

working example in jsFiddle

This can be achieved using div. It can be done with table too. But i always prefer div.

<body id="doc-body" style="width: 100%; height: 100%; overflow: hidden; position: fixed" onload="InitApp()"> 
    <div>
        <!--If you don't need header background color you don't need this div.-->
        <div id="div-header-hack" style="height: 20px; position: absolute; background-color: gray"></div>

        <div id="div-header" style="position: absolute; top: 0px; overflow: hidden; height: 20px; background-color: gray">                
        </div>

        <div id="div-item" style="position: absolute; top: 20px; overflow: auto" onscroll="ScrollHeader()">                
        </div>
    </div>
</body>

Javascript:
please refer jsFiddle for this part. Else this answer becomes very lengthy.

Share:
146,037
Admin
Author by

Admin

Updated on July 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I have been trying to figure out this problem i have with html/css sticky header + scrollbars. We are creating a program that requires scrollbars to show up once the containersize reaches a certain point(depending on resolution of the user).

    I am forcing a min-width on the second column in the table, so the table stops decreasing at a certain point and forces the container to stay at a certain width. The overflow on the container shows the horizontal scrollbar. Everything works fine. Once i add a second scrollbar for the vertical scrolling, things are getting messed up. Does someone have a solution for this problem? I want to have a vertical scrollbar on the .table-body, but the scrollbar must be visible on the outercontainer.

    Is there a good html/css solution for fixed header tables? I have been searching for a week, but can only find jQuery plugins for this kind of behaviour.

    This is my current HTML:

    <!DOCTYPE html>
    <html>
    <head>
        <title>fixed header prototyping</title>
        <link rel="stylesheet" href="css/style.css">
    </head>
    
    <body>
    <div class="outer-container"> <!-- absolute positioned container -->
    <div class="inner-container">
    
        <div class="table-header">
            <table id="headertable" width="100%" cellpadding="0" cellspacing="0">
                <thead>
                    <tr>
                        <th class="header-cell col1">One</th>
                        <th class="header-cell col2">Two</th>
                        <th class="header-cell col3">Three</th>
                        <th class="header-cell col4">Four</th>
                        <th class="header-cell col5">Five</th>
                    </tr>
                </thead>
            </table>
        </div>
    
        <div class="table-body">
            <table id="bodytable" width="100%" cellpadding="0" cellspacing="0">
                <tbody>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                    <tr>
                        <td class="body-cell col1">body row1</td>
                        <td class="body-cell col2">body row2</td>
                        <td class="body-cell col3">body row2</td>
                        <td class="body-cell col4">body row2</td>
                        <td class="body-cell col5">body row2 en nog meer</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
    </div>
    
    
    
    </body>
    </html>
    

    And my CSS looks like this:

    body {
        margin:0;
        padding:0;
        height: 100%;
        width: 100%;
    }
    table {
        border-collapse: collapse; /* make simple 1px lines borders if border defined */
    }
    tr {
        width: 100%;
    }
    
    .outer-container {
        background-color: #ccc;
        position: absolute;
        top:0;
        left: 0;
        right: 300px;
        bottom:40px;
        overflow: hidden;
    
    }
    .inner-container {
        width: 100%;
        height: 100%;
        position: relative;
        overflow-x: scroll;
        overflow-y:hidden;
    }
    .table-header {
        float:left;
        width: 100%;
    }
    .table-body {
        float:left;
        height: 100%;
        width: inherit;
        overflow-y: scroll;
    }
    .header-cell {
        background-color: yellow;
        text-align: left;
        height: 40px;
    }
    .body-cell {
        background-color: blue;
        text-align: left;
    }
    .col1, .col3, .col4, .col5 {
        width:120px;
        min-width: 120px;
    }
    .col2 {
        min-width: 300px;
    }
    

    JSFiddle example - http://jsfiddle.net/W8URM/

    Thanks in advance guys!

  • Netsurfer
    Netsurfer over 10 years
    Upvoted! I share your opinion that this cannot be achieved by pure CSS. IMHO your solution is exactly what was asked for. The original markup already isn't very semantically, because splitting a table's thead and tbody, plus wrapping each one in a DIV doesn't look "correct" to me.
  • user10
    user10 over 10 years
    @user1386906 you can add your own styles to grid cells and rows.
  • avrahamcool
    avrahamcool over 10 years
    I think you missed a big thing here, the header doesn't stick.
  • Jerzy Gebler
    Jerzy Gebler about 10 years
    Very simple and very good solution :), but if you need to use two or more tables on the same page you can implement the following code: $(window).load(function(){ $('table').on('scroll', function () { $(this).find(" > *").width($(this).width() + $(this).scrollLeft()); }); }); Thanks a lot Mathijs for the idea.
  • aron.duby
    aron.duby almost 10 years
    I want so badly for this to work perfectly, unfortunately if you click the scroll wheel to do mouse move scrolling in IE 10 & 11 it does the horizontal scrolling on the body and not the head, and doesn't even update the scroll bar. Any ideas on how to fix that one?
  • 9blue
    9blue over 9 years
    I have similar implement in my page as well, there is one issue that bothers me though: How do you handle the page in rtl direction, scrollLeft is not applicable anymore?
  • avrahamcool
    avrahamcool over 9 years
    @Zen without putting to much thinking into it, I'd say that you can replace left: -1*this.scrollLeft by right: -1*this.scrollRight. post a relevant fiddle, and we'll continue from there.
  • 9blue
    9blue over 9 years
    @avrahamcool scrollRight is not a value I can get from native javascript fiddle is here link based on your fiddle
  • Vivek Vikranth
    Vivek Vikranth over 9 years
    @avrahamcool Why your Tested on: IE10, IE9, IE8, FF, Chrome fiddle solution not working on ie8 while using jquery-1.7.2 can you please tell me
  • avrahamcool
    avrahamcool over 9 years
    @vikranth For IE I've tested it on my local machine.
  • AndyClaw
    AndyClaw about 9 years
    Same solution but without extraneous CSS (pet peave when demonstrating a CSS solution) jsfiddle.net/oozL98dx
  • Billy McKee
    Billy McKee about 9 years
    This solution forces a fixed column width. That takes away one of the table elements most useful features.
  • Billy McKee
    Billy McKee about 9 years
    This works pretty well until your content is > 100px wide. Then the TH width does not match the corresponding TD width.
  • Mathijs Flietstra
    Mathijs Flietstra about 9 years
    @BillyMcKee - You should check the original fiddle in the answer, the problem you mention only shows up in the version without the "extraneous" CSS. It seems a little bit too much CSS was removed in that version..
  • Billy McKee
    Billy McKee about 9 years
    @MathijsFlietstra That fiddle still doesn't work if the content is > 100px wide (with no line break).
  • Mathijs Flietstra
    Mathijs Flietstra about 9 years
    @BillyMcKee - Ah, I see, that could be fixed in this way. I realise that this fixes the columns widths, but since I never set out to come up with a solution which supports flexible column widths based on their contents, I don't think that's an issue. I'm kind of kicking myself for not including this in the first place, so thanks for pointing it out :)
  • Chris Andersson
    Chris Andersson over 8 years
    Nice solution. This should however be changed to CSS3 transform to use hardware acceleration instead of repainting with every scroll. jsfiddle.net/eZXtq/665
  • Neyer
    Neyer over 7 years
    Good idea, although I would like an alternative only using a table as such
  • kikovi
    kikovi over 7 years
    I made simplified version without inner & outer containers for my own needs. If anyone else needs it: jsfiddle.net/7Lgoaos7
  • avrahamcool
    avrahamcool over 7 years
    @kikovi your demo doesn't work well. the title hides the first content row, and we can see through the heading when we scroll, and the bottom scroll is visible only when we scroll to the bottom.
  • kikovi
    kikovi over 7 years
    @avrahamcool you are correct. I didn't polish the demo completely, because it already suited my needs. Here is the polished version, if anyone needs it: jsfiddle.net/kq1gzzmm. Bottom scroll depends of the container height and the title is set to position relative, so it doesn't hide first content row.
  • adolzi
    adolzi almost 7 years
    Is there any possibility of extending your solution (without jQuery) also to fix column (last or first)? I've tried to set position: absolute but then it's unscrollable..
  • Swoox
    Swoox over 6 years
    Cheers mate as css only solution this works like a charm.
  • tatsu
    tatsu over 6 years
    @Anshuman wondering if you can help out with my version of the question : stackoverflow.com/questions/47073223/… ? thanks.
  • tatsu
    tatsu over 6 years
    @MathijsFlietstra wondering if you can help out with my version of the question : stackoverflow.com/questions/47073223/… would you know what I'm missing?
  • tatsu
    tatsu over 6 years
    @avrahamcool wondering if you can help out with my version of the question : stackoverflow.com/questions/47073223/…
  • S..
    S.. about 6 years
    I tried this but my header is not scrolling horizontally. Any idea why? Please help.
  • Anshuman
    Anshuman about 6 years
    @N. B. - can you create a fiddle and share so that I can check what's wrong.
  • S..
    S.. about 6 years
    Hello @Anshuman, I was actually integrating it in a system using a framework with predefined CSS. That's why I guess it was not working. Lots of overriding was happening. I no longer need it anyway. Thank you for replying.
  • MatthewG
    MatthewG almost 6 years
    This isn't an HTML/CSS-only solution, you have an onscroll which is JavaScript.
  • user466130
    user466130 almost 6 years
    can somebody help out with my version of question:stackoverflow.com/questions/51578325/…
  • Anshuman
    Anshuman almost 6 years
    @MatthewG - agreed and edit has been done. Thanks for pointing it out
  • Wayne
    Wayne almost 5 years
    The header table and the body tables widths are not the same. It is noticeable when looking at the "yellow" header on the Fiddle; the yellow headers width is not the same as the "blue" table. I my case the situation is worse since I used a "fixed" position div, and then a 100% width of the non fixed position is not the same as the fixed positions 100%. To fix this one can use javascript and then set the widths to align them. e.g. onload="document.getElementById('thebody').style.width = document.getElementById('headerdiv').style.width;
  • Alfonso Tienda
    Alfonso Tienda almost 5 years
    There's still a problem: When content of cells are inputs, the scroll doesn't move when you change the focused imput with tabs. This one: jsfiddle.net/gtey5cz2 (all versions fail). @anshuman 's response worked; jsfiddle.net/nstb69pz
  • Martien de Jong
    Martien de Jong about 4 years
    I needed a version that works with input elements in the header too (and tab-scrolling) so I hacked the original fiddle into one that has a hidden scrollbar for the headers: jsfiddle.net/bmj4wkcL It's quick and dirty, feel free to improve if needed,
  • Ebrahim Abdollahian
    Ebrahim Abdollahian about 4 years
    if add direction:rtl to table this solution not work. Do you have any solution for that?
  • Sensei James
    Sensei James almost 4 years
    @Anshuman pardon me, your edit is still misleading. You saying you have "an HTML/CSS only solution (with a little JS)" is a contradictory statement - it can't be HTML/CSS only if it contains ANY other tech. It indeed contains a line of JS, so it is not HTML/CSS only.
  • Mathijs Flietstra
    Mathijs Flietstra almost 4 years
    @ebigood - response is a bit late :) but in order to make that work you'd have to swap the math around a bit as well: jsfiddle.net/fp9jra43