BlueCaret
BlueCaret

Reputation: 5000

Sticky Table Header with 100% height "panes"

Background: I am using CSS to create a web app like experience, where everything on the page is always visible, and only certain panes are scrollable. I now have a need to expand this to tables. I want the table header to always stay visible (and sometimes a footer) but the table body should be scrollable only.

What I have done so far is apply a "pane" class to the thead and tfoot, and then made the tbody auto fill the height and then make it scrollable. All of this works except that the thead, tbody, and tfoot are no longer 100% width. This method seems to get me the closest to what I want.

Fiddle: I have a JSFiddle that gets me close, it also demonstrates the code I'm using to create the fixed and scrollable panes. http://jsfiddle.net/va4HF/1/

Requirements: Ideally I would like to keep my pane css as it is, but adapt it when a table is needed. I'd also like to keep this CSS only.

The following code is my proof-of-concept code, and includes the Pane CSS as well.

HTML:

<div class="column">
    <div class="pane top">Top</div>
    <div class="pane middle">
        <table>
            <thead class="pane table-head">
                <tr>
                    <th>Header</th>
                </tr>
            </thead>
            <tbody class="pane table-body fill">
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
            </tbody>
            <tfoot class="pane table-foot">
                <tr>
                    <th>Footer</th>
                </tr>
            </tfoot>
        </table>
    </div>
    <div class="pane bottom">Bottom</div>
</div>

CSS:

body, html {
    height:100%;
    margin:0;
    padding:0;
}
div {
    box-sizing:border-box;
    box-sizing:content-box\9; /* Fix for IE9 sizing */
    -moz-box-sizing:border-box; /* Fix for firefox sizing */
}
.column {
    position:absolute;
    width:100%;
    min-height:100%;
    height:auto;
    overflow:hidden;
}
.pane {
    position:absolute;
    width:100%;
    overflow:hidden;
}
.fill {
    height:auto;
    overflow:auto;
}
.top {
    background:pink;
    height: 20%;
    top:0;
}
.middle {
    background:red;
    top:20%;
    bottom:50px;
}
.table-head {
    height: 40px;
    top:0;
}
.table-body {
    top:40px;
    bottom:40px;
}
.table-foot {
    height: 40px;
    bottom:0;
}
.bottom {
    background:orange;
    height: 50px;
    bottom:0;
}
table thead tr, table tfoot tr {background:rgba(0,0,0,0.5);}
table tbody tr {background:rgba(0,0,0,0.3);}
table td, table th {padding:10px; color:#fff;}

/* Fix for Safari scrollbars (also styles Chrome scrollbars) */
    .fill::-webkit-scrollbar {-webkit-appearance: none;width: 10px;}
    .fill::-webkit-scrollbar-track {background-color: rgba(0,0,0, .3);border-radius: 0px;}
    .fill::-webkit-scrollbar-thumb {border-radius: 0px; background-color: rgba(255,255,255, .4);} 

Research: Someone else has asked this with a similar situation at Table that Fills 100% Parent Height with Fixed Header/Footer but never got a good response and ended up going with Javascript, but I would like to try and find a CSS solution. Or at the very least a simpler Javascript solution then what he used (avoid having to overlay three tables)

Upvotes: 0

Views: 4043

Answers (2)

BlueCaret
BlueCaret

Reputation: 5000

After a lot of research to figure out all of my options for this I opted for going with separate tables for the header, body and footer and I surround each table with a div. I then style that div as a "pane". As long as the columns in the header table and the body table are set as the same width, they will line up.

There was some cleanup I had to do, one of which resulted in needing to keep the vertical scrollbar always showing, and then add a margin to the header and footer tables so that if the body starts to scroll or not, the headers will always line up.

It would be something like this:

    <div class="pane table-head">
        <table>
            <thead class="">
                <tr>
                    <th>Header</th>
                </tr>
            </thead>
        </table>
    </div>
    <div class="pane table-body fill">
        <table>
            <tbody>
                <tr><td>Text</td></tr>
                <tr><td>Text</td></tr>
                ...
            </tbody>
        </table>
    </div>
    <div class="pane table-foot">
        <table>
            <tfoot>
                <tr>
                    <th>Footer</th>
                </tr>
            </tfoot>
        </table>
    </div>

See updated JSFiddle: http://jsfiddle.net/bluecaret/va4HF/5/

This still isn't an ideal solution, I may end up ditching this and go with Fabio's solution of a div based table, although I can see potential issues with that as well based on some tests. For now this is what I'll be sticking with.

Upvotes: 1

Devin
Devin

Reputation: 7720

well, the first question is why are you using tables at all, but just in case use this:

table, th{width:100% !important; min-width:240px; }

where min-width is the minimum width for the table

Then again, you really should use divs: less, easier markups, no problems like this

Upvotes: 0

Related Questions