0

Oh, the golden days of table-based layouts. Shouldn't we all go back there and screw semantics? (I know, I know, ...)

But I have a tricky website layout that is done in seconds and very few lines of code if I use a table. I have been pulling my hair over achieving the same with divs for two days now. Maybe someone can help.

This is the layout I want to achieve: http://jsfiddle.net/reltek/13c6yfmh/

This is the code using tables, nice and easy:

<table border="1" width="100%">    
  <tr>
    <th rowspan="2" width="30%" valign="top">            
      <h2>Main Navigation</h2>
      <p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
      <ul>
        <li>Nav 1</li>
        <li>Nav 2</li>
        <li>Nav 3</li>
      </ul>
    </th>
    <td valign="top">
      <h1>Main Content</h1>
      <p>Flexible, might get really long.</p>          
    </td>
  </tr>
  <tr>
    <td height="3em">      
      <h2>Footer</h2>
      <p>flexible height, should stay at the bottom of the page.</h2>
    </td>
  </tr>
</table>

My div-based HTML can be found here: http://jsfiddle.net/reltek/48rmshen/

The problem is: the footer on the right doesn't stay at the bottom, if the left column is longer than the right one.

Any help appreciated, thanks everyone!

1
  • 1
    When it comes to <table>s their time is not solely in the past. If tables makes semantical sense they should be used. For example: if you want to display tabular data (something that would normally put in a spreadsheet) then you should use a table. So, honor thy tables and use them appropriately. Commented Mar 5, 2015 at 8:04

3 Answers 3

2

This is a job for flexbox (prefixing and workarounds for older browsers left as an exercise for the reader)

body {
    display: flex;
}
nav {
    background: red;
}
.non-nav {
    display: flex;
    flex-direction: column;
}
main {
    background: green;
    flex-grow: 1;
}
footer {
    background: blue;
    flex-shrink: 1;
}
<nav>
     <h2>Main Navigation</h2>

    <p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
    <ul>
        <li>Nav 1</li>
        <li>Nav 2</li>
        <li>Nav 3</li>
    </ul>
</nav>
<div class="non-nav">
    <main>
         <h1>Main Content</h1>

        <p>Flexible, might get really long.</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p>end of text</p>
    </main>
    <footer>
         <h2>Footer</h2>

        <p>flexible height, should stay at the bottom of the page.</p>
        <ul>
            <li>Nav 1</li>
            <li>Nav 2</li>
            <li>Nav 3</li>
        </ul>
    </footer>
</div>

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for pointing to flexbox, I prefer the clean document structure. But lousy browser support (virtually no IE) made me shy away from that option. But on second thought, including IE workarounds might work.
Market share of IE < 11 is dwindling (thanks in a large part to better defaults for Windows Update). Most people not using it are either in horrible corporate environments or stuck on Windows XP (which doesn't even get security updates now). Your need to care about old-IE really depends on who your target audience is.
That hits the nail: it's a corporate/university/scientific website. IE9 and even IE8 is pretty common still.
1

In keeping with your display:table in your example the following works. Here is the jsfiddle http://jsfiddle.net/r4pg8p25/2/

You can add and subtract your empty paragraphs and see it expand and contract in sync with the left hand panel.

Hope this helps, Tim

<html>
    <header>
        <style>  

            html, body { text-align: justify; height: 100%; }

            .layout { display: table;  height: 100%;}
            .layout .columns-container { display: table-row;  height: 100%;}
            .layout .columns-container .column { display: table-cell;  height: 100%;}
            .layout .top { display: table-row;  height: 100%;}
            .layout .bottom { display: table-row;  height: 100%;}
            .layout .top .main{ display: table-cell;  height: 100%;}
            .layout .top .footer{ display: table-cell;  height: 100%;}

            .one-third { width:33%; float: left;  height: 100%;}
            .two-thirds { width:66%; height:100%; float: right; }

            .main-footer { height: 100%; }

            .nav { background: red; padding: 20px; }
            .main { background: green; padding: 20px;  height: 100%; }
            .footer { background: brown; padding: 20px; height: 150px; }

        </style>
    </header>
    <body>
        <div class="layout">
            <div class="columns-container">
                <div class="column one-third">
                    <div class='nav'>
                        <h2>Main Navigation</h2>
                        <p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
                         padding-bottom:100%; margin-bottom:-100%;
                        <ul>
                            <li>Nav 1</li>
                            <li>Nav 2</li>
                            <li>Nav 3</li>
                        </ul>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>&nbsp;</p>
                        <p>end</p>
                    </div>
                </div>
                <div class="column two-thirds">
                    <div class="layout main-footer">
                        <div class='top'>
                            <div class="main" role="main">
                                <h1>Main Content</h1>
                                <p>Flexible, might get really long.</p>
                                <p>end of text</p> 
                            </div>
                        </div>

                        <div class='bottom'>
                            <div class="footer">
                                <section id="colophon" class="site-info" role="contentinfo">
                                    <h2>Footer</h2>
                                    <p>flexible height, should stay at the bottom of the page.</p>
                                </section>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>        
    </body>
</html>

3 Comments

Thanks Tim, I fiddled with it and it works exactly as planned. The amount of divs to achieve this effect is pretty big though. So I settled with a flexible height footer, which leads to a less cluttered document structure. Not the perfect solution designwise, but I guess I will just wait for better flexbox support.
Not a problem, I would've done the same. As a matter of fact I saw that answer @Quentin before I started this. I figured it's always good to see multiple ways to accomplish the same thing and I thought you'd appreciate seeing it done the way you started it. Have a great one.
You might want to accept an answer as correct (based on the question you asked). You've let it sit awhile. Best.
1

You can make use of display:table but unfortunately you can't do rowspan so you need to get a bit creative with the div structure:

html, body {
    min-height:100%;
    padding:0;
    margin:0;
}
#wrapper {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
}
.table {
    display:table;
    width:100%;
    height:100%;
}
.row {
    display:table-row;
}
.cell {
    display:table-cell;
}
#left-column {
    width:30%;
    background:red;
}
#right-column {
    width:70%;
    height:100%;
}
#content, #header {
    height:100%;
}
#header {
    background-color:green;
}
#footer {
    background-color:blue;
}
<div id="wrapper">
    <div class="table">
        <div class="row">
            <div id="left-column" class="cell">
                 <h2>Main Navigation</h2>

                <p>Might get really long, sometimes even longer than the Main Content and Footer combined.</p>
                <ul>
                    <li>Nav 1</li>
                    <li>Nav 2</li>
                    <li>Nav 3</li>
                </ul>
            </div>
            <div id="right-column" class="cell">
                <div id="content" class="table">
                    <div id="header" class="row">
                        <div class="cell">
                             <h1>Main Content</h1>

                            <p>Flexible, might get really long.</p>
                        </div>
                    </div>
                    <div id="footer" class="row">
                        <div class="cell">
                             <h2>Footer</h2>

                            <p>flexible height, should stay at the bottom of the page.</p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Example Fiddle

3 Comments

Thanks Pete, this is exactly what I wanted to achieve! I was hoping for a simpler document structure that doesn't just mimic the table structure. But this seems to be the way to go.
You could use the flex structure (depending on what browsers you need to support) in Quentin's answer and just make it stretch to 100% height.
Unfortunately, website traffic will be pretty IE-heavy... :-( 100% height won't be necessary as the part in question is just a fraction of the whole page (adding header, etc.).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.