Tuesday, March 09, 2010

Three equal length columns in CSS

So you're happily using inline-block to line-up columns next to each other and added that damn IE7 inline block fix to make that detestable bit of software work, but what's this? When I colour them in the div blocks height only matches that of the containing text. I could make them all a fixed height, but what if I add text to a column and it increases the height. Isn't the point of CSS so I don't have to keep tweaking every single page?


Yes  it is. So how to make it work and all in pure CSS. In practice it's really simple, in principle more complicated.

First up let's imagine we've got our three inline-block differently coloured columns - a 10em, a 20em, and a 30em in height created from the content within each block. First of all, if you haven't already, let's make it nice and neat by dropping them all into one div so our pseduo-code looks like this

<div id="container">
<div id="10emcolumn"></div>
<div id="20emcolumn"></div>
<div id="30emcolumn"></div>
</div>

The first thing to note is that the height of our container is that of the largest div, so it's set implicitly to 30em in height. Now to set a couple of parameters called margin and padding.

Although to most these may seem identical they operate in different ways. Imagine a 10em square green div with white backgrounded text filling it. With a margin:0 and padding:0 we should only see a white background. Change margin to 1 and we get a 10em square with an 1em green border surrounding an 8em white square filled with text. Set padding to 1 instead and we get an all white square again but with the text confined to an 'invisible' 8em square. Set both to 1 and we get a 10em square with a 1em green 'border' and an 8em white square with the text in an 'invisible' 6em square. Or at least that's the theory; in practice you'd be surprised how some browsers just don't get this.

Anyway enough of the diversion, my currently smallest div is 10em the largest is 30em  and I don't think I'm going to go beyond 50em so I'll add a "padding-bottom: 50em;" to each of the column div's.

Big Whoop now I have exactly the same as before just with more white space.

So here's the unintuitive part I add to each column a "margin-bottom: -50em". Oo look nothing's happened; ah but it has you see the container div takes its height not from the padding but from the margins of its contents. Change just the padding and the margin expands to match as does the container, so shrink the margin and the container drops to match it.

The reason nothing appears to have changed is because by default browsers will happily draw outside the boundaries of a div. So let's tell it not to. This excess is logically called the overflow; so set the container div with "overflow:hidden" and anything that would appear outside it vanishes.

So the padding pushes the column height down and the negative margin brings the container div back up to the actual content height, then we just hide the overflow.

Stupid, but until CSS3 gives us some decent vertical/height tools it's the best option available.

0 comments: