Equal-height, 100% height columns with CSS and JavaScript
Friday, January 5th, 2007Yes, that title was a mouthful. But, you know the idea: you have a CSS-based two-column layout, and you want both columns to always be the exact same height. Maybe you have a narrow left navigation column with a background color (or a gradient) and a wide right content column; if you want that background color to appear for the entire height of your content column, then you’ll need this trick, otherwise, it’ll stop when it reaches the height of its container.
Here’s an example of what we’re looking to achieve in a layout I built at my day job over at TheLadders.com. In this case, the left-hand column has a solid color fading into a gradient at the bottom of our content block. Since the right column will stretch that block down, we need to force the left-column to have the same exact height as the right column. How do we go about doing that?
There are plenty of ways to do make equal height columns using crazy CSS hacks and other methods. They work well, but they’re not very clean. To make it nice and easy, we need to use JavaScript for its main purpose: controlling presentation. And, we’ll only need a few lines of code to do it.
The Set-up
Here’s some example CSS to get that two-column look:
div#container{
width:800px;
}
div#container div#leftColumn, div#container div#rightColumn{
float:left;
}
div#container div#leftColumn{
background-color:#CCC;
width:250px;
}
div#container div#rightColumn{
margin-left:50px;
width:500px;
}
There’s a two-column layout for you. Here’s what that would look like with some example, placeholder content.
The JavaScript
See? That right column extends far past the left column, but we can take care of that with a simple JavaScript function (I had to add a line wrap to fit everything in the page; remove it to actually use the function):
function equalColumns(){
var l = document.getElementById('leftColumn');
var r = document.getElementById('rightColumn');
r.offsetHeight >= l.offsetHeight ? l.style.height = \\ line wrap
r.offsetHeight + "px" : r.style.height = l.offsetHeight + "px";
}
Let’s examine what this function does. First, we store references to our two columns. Then, we do the dirty work, using the ternary operator for our comparison. Let’s examine what it’s doing:
- offsetHeight is an element’s rendered height, the total height it takes up in the browser window.
- If the right column is taller than the left, we set the left column’s CSS style height property to the right column’s height, then add "px" since CSS demands a unit of measure, and offsetHeight is measure in pixels.
- What if the left column is taller than right right? We do the same thing: find the left columns offsetHeight in pixels, and assign that to the right column’s CSS height.
Now that we have this function, we’ll add it to window.onload or the body tag’s onload attribute. You can use the addEventListener / attachEvent combination, too. As soon as the body loads, our columns will snap to the same height.
There’s one problem with this little method: if your pages are larger in size you’ll see them finish rendering, the onload event will trigger, and you will see the columns’ height being set (the background image or gradient will jump from its orginal height to its new height). It looks choppy, like you see here.
Can we fix it? Of course! Why run that function onload when you can run it immediately after the columns load in the document?
We’ll move that onload function into a script tag, and place that script tag containing our function immediately after the close tag of our second column. This means that the script will run immediately after that second column loads in the document, and the user will never see anything choppy. The height will be set before content finishes rendering and appears in the browser. Case closed. And, you now have equal columns as seen here. (Unless you’re stuck with using onload?)
But what about that gradient?
If you’ve been looking at the gradient here, you’re probably wondering how that shows up. Well, that’s a topic for another article coming soon.
(It’s right here now.)
A Google search can turn up many, many equal height column sites, but, of those I looked at, here’s one of the best (and they have a script modified to take padding into account, something that I didn’t need when I wrote my version for TheLadders).
technorati tags:design, css, javascript, equal height columns, layouts
Stuck with using onload? We can smooth out the height jump by adding a few bits to our CSS and another line to our JavaScript. We’ll change our CSS to:
div#container div#leftColumn{
width:250px;
}
div#container div#leftColumn.bg{
background-color:#CCC;
}
And, we’ll add a single line to our JavaScript function (and remove that line break I had to add):
function equalColumns(){
var l = document.getElementById('leftColumn');
var r = document.getElementById('rightColumn');
r.offsetHeight >= l.offsetHeight ? l.style.height \\ line wrap
= r.offsetHeight + "px" : r.style.height = l.offsetHeight + "px";
l.className = "bg";
}
Now, our background color is applied after the new height is set. This looks much more natural, almost as if a background image is being loaded and applied. If you’re using an image heavy site, odds are users will never notice.