The search for a technique that offers real equal height columns leads nowhere because we don't have full vertical control in current CSS 2.1 implementations cross browser
This is how Ingo Chao start his article presenting a method to create a css-based layout with equal height columns. Having columns with equal heights is not something always easy to do if you only rely on CSS, and beside the Faux column method, I'm not aware of any stable way to create equal height columns using only CSS without any extra markup.
After some more research on the subject, the solutions I found were either buggy or complicated to implement, so I decided to experiment with all these methods to create a simple and flexible method, that would load the content before the sidebars, that could be either fluid, fixed or grid-like, and of course, work across all browsers.
I have to admit that I REALLY thought that I was inventing something, until I found this article from Paul O'Brien. His method uses the same positionning trick as the one I use for the columns.. My only real contribution would be to make a fusion of a holy-grail-like method with the O'Brien method. The final layout can be modified very easily, switched from fluid to fixed or grid-like on demand, loads the content before the sidebars (content->left->right), can be adapted to as many columns as you want, works on pretty much all browsers, and of course, simulate equal heights columns.
Quickly explained
Like the O'brien method, I use an extra <div> (I know, shame on me!) for each column. Then I position them absolutely and this is where the real magic is happening. A normal block with a height of 100% can only fill its container if the container itself have a height. But this doesn't apply if the block is positioned absolutely. So if I position the block to the bottom and give it a height of 100%, it creates a background for the column that will extend until the footer of the page. Do this for each column, and you end up with a layout with equal height column.
Here are some examples of the final layouts, and some HTML slides that present the method step by step.
The concept step by step

- You start with a normal layout.

- We won't be using the 'real' columns to have a background.

- Instead, we add three
<div>at the bottom of the page, that have the same class as their respective columns, so the<div>are aligned with their columns. 
- The
<div>are positioned absolute. 
- Give each
<div>aheightof 100%, and positioning to the bottom creates the full-height columns. 
- Bring the content back up with
z-index:2;and voilà !
A closer look at the code
here is the original markup I use. It could be a little bit lighter if you consider that IE is not worth worrying about, as #main is only used to fix a clearing issue.
<div id="page">
<div id="header">...</div>
<div id="main">
<div id="content">
<div id="content-inner" class="column center">...</div>
</div>
<div id="left" class="column left">...</div>
<div id="right" class="column right">...</div>
</div> <!-- /main -->
<div id="footer">...</div>
</div><!-- /page -->
Here is a graphical representation of the <div>:

The base Layout
Let's have a closer look at how the layout is created. First of all, I always start with a simple browser reset.
*{
margin:0;
padding:0;
}
Then we can start setting up the layout. We add some colors to see what we're doing:
#header, #footer{background-color: #ccc;}
#left{background-color:#d7ecff;}
#right{background-color:#daffc6;}
#content-inner{background-color:#fff2d7;}
Setting up the width of the sidebars.
.left {
width: 220px;
}
.right{
width: 150px;
}
Then prepare the content to compensate for the sidebars once they are positioned correctly.
#content-inner {
margin-left: 220px;
margin-right: 150px;
}
Bringing the sidebars back at the same level of the content, using the #content and by floating all columns.
#content {
float:left;
width:100%;
margin-right:-100%;
}
.column {
float:left;
}
A quick insurance for IE to work properly... un-floating the center column.
#content-inner {
float:none;
margin-left: 220px;
margin-right: 150px;
}
The right sidebar shouldn't be floating left, but right.
.right{
float:right;
width: 150px;
}
Last touch, the footer should clear the columns. Plus some styles.
#footer, #header{
clear:both;
text-align:center;
font-size:2em;
}
The layout is done, so you should have something like this. So far so good, it works across all browsers without any hacking. But you'll notice that all the column have a different height, and this is what we are now going to fix.
The Equal Height Columns
Firts, let's add the empty <div> (blush). Notice how we give the same class right, left or center to the empty <div> so they behave like their corresponding columns.
<div id="page">
<div id="header">...</div>
<div id="main">
<div id="content">
<div id="content-inner" class="column center">...</div>
</div>
<div id="left" class="column left">...</div>
<div id="right" class="column right">...</div>
</div> <!-- /main -->
<!-- These are used to create the columns background -->
<div id="bgcenter" class="bg center"></div>
<div id="bgleft" class="bg left"></div>
<div id="bgright" class="bg right"></div>
<div id="footer">...</div>
</div><!-- /page -->
As these <div> are empty, you shouldn't notice any difference in your layout. In order to see our work, we are going to change the color rules to be applied on these empty <div>.
#bgleft{background-color:#d7ecff;}
#bgright{background-color:#daffc6;}
#bgcenter{background-color:#fff2d7;}
Now that we have the colors applied on the futur 'fake columns', let's start the magic. First, as we are going to position the fake columns, and reset their relative element to the #page element.
#page{
position:relative;
}
Now we can position the fake columns and give them a height. It is very important to position these at the bottom, for browser compatibility.
.bg{
position:absolute;
bottom:0;
height:100%;
}
Then we can override these general rules for each column to position them correctly and with the right width.
#bgleft{
left:0;
}
#bgright{
right:0;
}
#bgcenter{
right:0;
width:100%;
}
Notice how we can give a width of 100% to the content as it's loaded before the other columns, so it'll show up under them. Now everything is fine, but the fake columns are showing up on top of the content... not good, so in order to bring the content back up, I just need to play with it's z-index of the content:
#content, #left, #right, #header, #footer{
position:relative;
z-index:2;
}
There you go! All columns appear to be the exact same height, and you can even style each one of them independently. But of course, as I said a little bit earlier, all versions of IE before version 8 need a little bit of tweaking. Nothing serious though... drop this in your <head> and it should fix it all !
<!--[if lt IE 8]>
<style type="text/css">
/* Only Hack for IE */
#main, #page{ height:1%; }
.bg{ height:1000em; }
</style>
<![endif]-->
I prepared some examples of this method, with fluid or fixed width, and even with a "fluid grid example". Except for the extra markup, the only drawback that I could think about this method is that the header and footer needs to be hiding the columns. It might be ok for simple projects, but maybe a little bit tricky for more complex layouts.
I also worked on integrating this method with a full height layout, so the footer remains at the bottom of the view port if the page isn't long enough. The result is fairly stable, except for Opera... still need some work, it's getting very close to a full-featured and flexible layout, only using CSS.
Update
Added a new example, per buckthorn's comment, with no extra markup needed. The columns are created only with CSS using the :before and :after pseudo class with the content. (not working in IE6/7 or FF2)
References
- A List Apart: Faux Columns
- http://alistapart.com/articles/fauxcolumns/
- A List Apart: In Search of the Holy Grail
- http://www.alistapart.com/articles/holygrail
- A List Apart: Creating Liquid Layouts with Negative Margins
- http://alistapart.com/articles/negativemargins
- Ingo Chao: Companion column method
- http://www.satzansatz.de/cssd/companions.html
- CSS layout: 100% height with header and footer
- http://www.xs4all.nl/~peterned/examples/csslayout1.html
- How to Make Equal Columns in CSS
- http://www.search-this.com/2007/02/26/how-to-make-equal-columns-in-css/
- Position is Everything: In search of the One True Layout
- http://www.positioniseverything.net/articles/onetruelayout/
This is not wordpress, it's
This is not wordpress, it's Drupal, and yes, I did it myself :)
Very nicely done. Now, how
Very nicely done.
Now, how do I add border to these, say 2-column, layout with margin to separate them?
What about using css on the
What about using css on the fake columns ?
You can style the columns using css the same way you can style any element of the page.
something like this :
border-right:1px solid #ccc;
}
Makes sense ?
Fabulous!!! In the .css, is a
Fabulous!!! In the .css, is a .center definition needed for this markup: ?
You're right, it's not. It
You're right, it's not. It just inherited from my coding habits. But in this case, you don't need it.
A very neat method... and a
A very neat method... and a lovely Drupal theme too! Cheers!
Incidentally, the absolutely positioned element for each column can be nested inside its column so long as the column is positioned and the absolutely positioned element has no left position value. Keeps the HTML code tidy.
This method works great. I
This method works great. I rarely print, but I noticed when I print an example page from this site and my own equal-column-height pages, the formatting and .css are ignored. Is this just an error in my .css, or has anyone else experienced this, too?
My bad, I didn't really paid
My bad, I didn't really paid attention to the print.css
I'll try to find some time to work on this
Wow, thanks for the speedy
Wow, thanks for the speedy reply. Sounds great. In the meantime, I'll work on a print.css that uses conventional columns and see how that goes. The screen versions are really ingenious, though.
Very good job, guy. I have a
Very good job, guy. I have a problem that I supose it has to be with the header and footer problem with headen columns, so is the links in footer doesn't work.
Any suggesiont?
Thanks!
I liked the idea behind this
I liked the idea behind this solution, but was hesitant to throw in the extra markup. So I added a generated content rule to the css for each column. E.g.,
#nav-col:after {
content: '';
position: absolute;
bottom: 0;
height: 100%;
width: 195px;
background-color: #f7f5e8;
z-index: 500;
}
#content:after {
content: '';
position: absolute;
left: 195px;
bottom: 0;
height: 100%;
width: 683px;
padding: 0 30px;
background-color: #fff;
z-index: 500;
}
In my limited testing so far, this seems to work in Safari, Firefox, and IE8. Of course more needs to eb done for IE7 -- and for IE6 you probably need to revert back to the One True Layout approach with the the huge bottom padding and negative margins. Not a big deal.
It is a nice alternative, and
It is a nice alternative, and will be, hopefully in short(ish) term the way to go.
I got inspired by your idea,
I got inspired by your idea, and decided to create a preview that I added to the list of examples.
The columns are created only with CSS, and don't need any markup at all. It's very clean, but it doesn't work for Internet Explorer before version 8, or Firefox before version 3.
http://www.couzinhub.com/files/ehc/ehc-fluid-grid-markup-free.html
There is a way to simulate
There is a way to simulate the content:after pseudo element in IE 7. It goes something like this:
#nav-col>*:first-child, #content>*:first-child {
height: 1000em;
}
Obviously this might not cover all situations (what does?); it really depends on your design and content. I should give credit to the site where I found this:
http://nanobox.chipx86.com/blog/2006/07/before-and-after-in-ie7-and-belo...
But even if this doesn't work for you, handing off a different solution to IE 6 and 7 is pretty easy via conditional comments.
It's not clear to me how this
It's not clear to me how this IE solution works.
/* Only Hack for IE */
#main, #page{ height:1%; }
.bg{ height:1000em; }
Wouldn't this just make those columns 1000em high? Equal height, yes, but far higher than the content requires on many pages. Unless there's some sort of "magic" that I'm missing. I'm still seeking an adequate solution for IE7.
After further testing, I
After further testing, I going to take back my last comment about IE 7 possible ways to fake the :after pseudo element. There does not appear to be good way to apply this solution to IE 7 without some extra markup. So one is free to choose between the solution described on this page or go back to faux columns for IE 7 via conditional comments. (I'm not even going to discuss IE 6). And then hope that IE 7 usage dwindles quickly and becomes insignificant enough to ignore.