5
votes

I've been working for a HTML/CSS fluid-width, fluid-height, fixed header table without success. I'm hoping you can point me to a JavaScript or jQuery solution.

Criteria:

  1. table must fill entire width of browser window (at least container)
  2. table must fill entire height of available container in browser window
  3. tbody must scroll y if there's not enough room for all rows
  4. thead th and tbody td columns must line up

Pure HTML/CSS is a bust. How about jQuery or JavaScript?

Here's a fiddle: http://jsfiddle.net/JXWfC/6/

Ultimately it will need to work on IE7+, and modern versions of Chrome and FireFox.

Here's some markup of my basic page:

<div class="container">
    <div class="sidebar">
        nav here
    </div>
    <div class="content">
        <table>
            <thead>
                <tr><th>column 1</th><th>2</th><th>three</th><th>this is column four</th></tr>
            </thead>
            <tbody>
                <tr><td>data</td><td>can</td><td>have</td><td>different widths: not all the same</td></tr>
                <tr><td>table</td><td>-</td><td>should</td><td>fill 100% width and 100% height</td></tr>
                <tr><td>and</td><td>-</td><td>should</td><td>not require all td's to be same width</td></tr>
                <tr><td>but</td><td>-</td><td>percentage</td><td>% widths are just fine</td></tr>
                <tr><td>and</td><td>if</td><td>there's</td><td>too many rows, it should scroll y (overflow-y: scroll)</td></tr>
                <tr><td>sample</td><td>1</td><td>row</td><td>Lorem ipsum dolor sit amit.</td></tr>
                <tr><td>sample</td><td>1</td><td>row</td><td>Lorem ipsum dolor sit amit.</td></tr>
                <tr><td>sample</td><td>1</td><td>row</td><td>Lorem ipsum dolor sit amit.</td></tr>
                <tr><td>sample</td><td>1</td><td>row</td><td>Lorem ipsum dolor sit amit.</td></tr>
            </tbody>
        </table>
    </div>
</div> 
2
Why is pure HTML/CSS a bust? Your criteria don't seem very demanding. - adamb
@adamb, I wasn't able to make it work. Can you show me? From my research this is a common problem. Yes, it doesn't seem too demanding, but there are a couple significant challenges — 1) height is always a challenge, 2) overflow scroll only works when table cells are display:block which ruins fluid width alignment of columns (you can set a static pixel width for each column, but not by fluid percentages). This is what led me to seek a js solution. But I'd be overjoyed to be wrong here. ;) - Ryan
When you say you want the table to fill the entire height, do you mean the table cells need to vertically expand? For example, if my page is 900px tall and I have only 3 rows in the table, should they each be 300px tall? If not, could you clarify what you need? - DACrosby
I see the confusion. Here's a picture here: i.stack.imgur.com/S42xy.png - Not the cells, but the visible rows. So if your window is 900px tall and only 3 rows, they should all be (let's say) 20px tall (standard height). but if there were 500 rows, you should be able to see (let's say 45 rows), but scroll to see the rest, but keep the header visible the whole time. Oh, and if it's not too much to ask... fill the table all the way to the right either way. So if your container can stretch 1200px wide, each tr should be 1200px wide as well. - Ryan

2 Answers

2
votes

This isn't complete and hasn't been checked in anything but Chrome, but hopefully it'll get you on the right track.

Basically the approach is to make the container position:relative; and the th tags all position:absolute;. This requires quite a bit of extra code for correct positioning, but it's a decent method to make the header always stay and the table cells scroll.

Alternatively you could make the headers a separate div from the table, but you'll still need to set widths so the columns line up. A horse a piece, really.

http://jsfiddle.net/daCrosby/JXWfC/9/

<div id="hold">
    <div class="header">
        <h4>title goes here</h4>
    </div>
    <div class="container">
        <div class="sidebar">sidebar<br />nav<br />goes<br />here</div>
        <div class="content" >
            <table>
                <thead>
                    <tr>
                        <th class="col1">column 1</th>
                        <th class="col2">2</th>
                        <th class="col3">three</th>
                        <th class="col4">this is column four</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td class="col1">data</td>
                        <td class="col2">can</td>
                        <td class="col3">have</td>
                        <td class="col4">different widths: not all the same</td>
                    </tr>
                [ ... ]

CSS

body{
    background:#000;
}
div {
    display:inline-block;
    vertical-align:top;
    -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}
#hold{
    display:block;
    padding:40px 10px;
    width:95%;
    margin:auto;
}
.content table,
.header,
.container{
    width:100%;
    max-height:100%;
}
.header {
    background:darkgray;
    color:white;
    text-align:center;
}
.container {
    background:lightgray;
}
.sidebar {
    width:20%;
    background:green;
    color:white;
    float:left;
}
.content {
    width:80%;
    position:relative;
}
h4 {
    margin:0;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
    background:red;
    overflow-y:scroll;
    height:300px;
    display:block;
}
thead {
    position:absolute;
    top:1px;
    left:0px;
    right:0px;
}
tbody{
    padding:1.3em 0px 0px;
    margin:0px;
    display:block;
}
tr{
    width:100%;
    display:block;
    margin-top:-2px;
}
th {
    background:#666;
    color:#fff;
    position:absolute;
}
td {
    display:inline-block;
    margin:0px;
    padding:0px;
    background:#ddd;
}
td.col2,
td.col3,
td.col4{
    margin-left:-4px;
}
.col1 { width:20%; }
.col2 { width:10%; }
.col3 { width:20%; }
.col4 { width:50%; }
th.col1 { left:0px; right:80%; }
th.col2 { left:20%; right:70%; }
th.col3 { left:30%; right:50%; }
th.col4 { left:50%; right:0x; }
0
votes

Is this you want? Working example

<div class="container" style="overflow:scroll;">
    <div class="sidebar">nav here</div>
    <div class="content">
        <table>
            <thead>
                <tr>
                    <th width=25%>column 1</th>
                    <th width=25%>2</th>
                    <th width=25%>three</th>
                    <th width=25%>this is column four</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>data</td>
                    <td>can</td>
                    <td>have</td>
                    <td>different widths: not all the same</td>
                </tr>
                <tr>
                    <td>table</td>
                    <td>-</td>
                    <td>should</td>
                    <td>fill 100% width and 100% height</td>
                </tr>
                <tr>
                    <td>and</td>
                    <td>-</td>
                    <td>should</td>
                    <td>not require all td's to be same width</td>
                </tr>
                <tr>
                    <td>but</td>
                    <td>-</td>
                    <td>percentage</td>
                    <td>% widths are just fine</td>
                </tr>
                <tr>
                    <td>and</td>
                    <td>if</td>
                    <td>there's</td>
                    <td>too many rows, it should scroll y (overflow-y: scroll)</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>1</td>
                    <td>row</td>
                    <td>Lorem ipsum dolor sit amit.</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>1</td>
                    <td>row</td>
                    <td>Lorem ipsum dolor sit amit.</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>1</td>
                    <td>row</td>
                    <td>Lorem ipsum dolor sit amit.</td>
                </tr>
                <tr>
                    <td>sample</td>
                    <td>1</td>
                    <td>row</td>
                    <td>Lorem ipsum dolor sit amit.</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>