Two Columns of Variable But Equal Height Using Simple CSS and a Couple of DIVs

If, like me, you cut your web development teeth during while CSS was still in its infancy, you likely put together a lot of sites that featured two (or more) columns decorated with bgcolors or background images that flowed together in lockstep, always retaining equivalent height. It was pretty standard and basically came along free with tables for layout.

Then? Along came CSS, the separation of style and content (don’t forget behavior!) and the two columns living in perfect harmony became a casualty of the war against crufty code.

Which brings us to this post. I’ve played around with a similar technique before, but I’d never taken it to this, it’s logical conclusion. This technique grew out of some conversation at work. I don’t remember the specifics, but I remember I was looking at some unrelated piece of code on someone else’s monitor. Walking back to my desk it reminded me of one thing or another and then the pieces started to tumble around in my head. It was a couple of hours later, on my drive home from work, when they clicked into place and I thought, “hey, I could fake that old technique!”

The basic idea goes a little something like this: just because a background color or gradient appears to be part of an element, that doesn’t mean it needs to actually be applied directly to that HTML element. Instead, using some basic CSS and a repeating background image we can fake that two column look by positioning the two columns on top of the “columns” formed by the background image . As long as the containing DIV grows with either of the columns and the gap in the background image matches the background (or is transparent, wlloing the background to show through) the illusion is maintained.

It’s like magic.

Here’s the sample (which I only tested in FF2 and IE7):

Here’s the CSS:

/*the two-column container*/
#container #two-columns {
	/*set that background image*/
	/*repeat it and center it*/
	background: url(images/bg.jpg) repeat-y center;
	height: auto;
	width: 500px;
	margin:auto;
	margin-bottom:20px;
}
#container #two-columns #column-2 {
	/*float it*/
	float:right;
	height: auto;
	width: 215px;
	padding:5px;
}
#container #two-columns #column-1 {
	height: auto;
	width: 215px;
	padding:5px;
}
/*clear the above float*/
#container .clr {
	clear:both;
}

and here’s the HTML:

<div id="two-columns">
<div id="column-2"> A column in structural engineering is a vertical structural element that transmits, through compression, the weight of the structure above to other structural elements below. </div>
<div id="column-1"> A column in structural engineering is a vertical structural element that transmits, through compression, the weight of the structure above to other structural elements below. </div>
<div class="clr"></div>
</div>

I told you it was simple. If you’re familiar with modern layout techniques the above should be commonplace. The interesting bit (to me at least) is the concept of pulling the “background” of the two columns off of the columns themselves and onto the containing DIV. This separation can be a powerful technique. I’ve used it before in a different context, but I think this example really illustrates how useful it can be. I’m already starting to see other possibilities for this pattern.

Expanding the toolbox is fun.

Of course, before I can actually use this technique where it’s most needed by me, I have to come up with a scheme that works with both variable width and variable height. Tricky stuff. If I can pull that of, I’ll install it right on my home page. As it stands now I’m using JavaScript to equalize the heights on the two news DIVs at the bottom.

Boo.

The good news is I’ve actually made some progress with the variable width/height version. Unfortunately, nothing is quite ready for prime time though so that’ll have to be unveiled in another post. Keep your eyes peeled and your fingers crossed. I’ll keep at it with the typing.

Posted in CSS

Leave a Reply

Your email address will not be published. Required fields are marked *