Reputation: 5000
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
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
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