Equal Height Columns with Cross-Browser CSS

by Matthew James Taylor on 17 October 2008

Equal Height Columns with Cross-Browser CSS and No Hacks

Creating equal height columns with CSS is not as easy as it may first seem. This tutorial highlights the display problems that occur with multiple column layouts, and then shows a simple solution that works in all common web browsers. The method shown here is 100% CSS hack-free, image-free and JavaScript-free so it can even be used on the most strictly coded websites.

For those who want some action immediately check out my demo pages: 2 column, 3 column, 4 column and 5 column. Also see my Perfect multi-column CSS liquid layouts - these use the same equal height column CSS principles as discussed below.

The problem with equal height columns

Unequal height columns look bad

In the example above we have three columns each with a different amount of content. You will notice that the problem is the column background colours stretch only as far down as the height of the content they contain. This is the problem we are trying to solve. How can we make all columns the same height? Or more specifically, how can we make all columns the same height as the tallest column? This is a tricky thing to do because we will never know exactly how high each column will be or which one will be the longest. We can't simply give all columns an arbitrary height either as this will cause big spaces at the end of the page if there is only minimal content, and if there is too much content then the columns will end before the text does. Neither of these situations are desirable. The fact is, content length is dynamic so the heights of each column must also be dynamic. We must remember that nothing is 'fixed' on the web, people have different screen resolutions and the text in their browsers can be set to any size, all of these things can affect the height of content.

Separating the column content from it's background colour

The first step to solving the equal height problem is to break it into smaller pieces that can be solved separately. The way we do this is to use two divs for each column instead of one. The first div will be used to hold the content and the other will be used as the background colour. This separation gives us individual control over these elements plus we can put them together in a more useful way. This will all become clear shortly.

A floated container div will always be the height of it's floated contents

This is the central principle behind this equal column height method. The only way to make the height of a div equal to the tallest column is if that div contains all the columns. So to explain this another way, by placing the columns inside a container we cause the container to be the height of the tallest column. This is a very useful structure.

Container div is the height of the tallest column

Three column HTML div structure

In the example above the three content columns are inside a container div.

<div id="container1">
    <div id="col1">Column 1</div>
    <div id="col2">Column 2</div>
    <div id="col3">Column 3</div>
</div>

Three column CSS

And here is the CSS that forces the container div to the height of the longest column.

#container1 {
    float:left;
    width:100%;
}
#col1 {
    float:left;
    width:30%;
    background:red;
}
#col2 {
    float:left;
    width:40%;
    background:yellow;
}
#col3 {
    float:left;
    width:30%;
    background:green;
}

For this structure to work correctly in all browsers the container div must be floated (left or right) plus each of the column content divs must also be floated, it does not matter which way. The process of floating the content divs makes them line up horizontally across the page. Floating the container makes it stretch down to the height of the tallest column inside. If we don't float the container then the content divs will stick out of the container at the bottom and the container won't have the correct height. Actually in this example the container will end up with a height of zero if it is not floated.

Adding extra nested containers

The next step to equal height columns is to add extra containers so they are nested inside each other. We need the same number of containers as we do columns - three. These three containers are going to be the backgrounds of each column. Notice that we have removed the background colours from the original columns and added them to the containers.

Three containers around the three columns

Three column HTML div structure

The two extra containers have been added to the HTML below.

<div id="container3">
    <div id="container2">
        <div id="container1">
            <div id="col1">Column 1</div>
            <div id="col2">Column 2</div>
            <div id="col3">Column 3</div>
        </div>
    </div>
</div>

Three column CSS

All the elements are floated to the left and the containers have a width set to 100% so they stay the full width of the page. The background colours have been removed from the content divs and added to the containers.

#container3 {
    float:left;
    width:100%;
    background:green;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
}
#container1 {
    float:left;
    width:100%;
    background:red;
}
#col1 {
    float:left;
    width:30%;
}
#col2 {
    float:left;
    width:40%;
}
#col3 {
    float:left;
    width:30%;
}

Moving the containers into place with relative positioning

Using relative positioning we now move the containers to their new locations. When each container is moved the divs become visible below. It is the layering and position of the coloured containers that create the background of the equal height columns. The container2 div is moved to the left by 30% to reveal the green right-hand column and the container1 div is moved to the left 40% to reveal the yellow center column and at the same time the red section that is still visible becomes the left-hand column.

The container divs are moved with relative positioning so the columns colours are exposed

The CSS relative positioning rules

Here is the CSS showing the the addition of relative positioning.

#container3 {
    float:left;
    width:100%;
    background:green;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:30%;
}
#col2 {
    float:left;
    width:40%;
}
#col3 {
    float:left;
    width:30%;
}

Moving the content back into each column

The next thing to do is to move the content of each column back onto the page so that it aligns with the column background colour underneath. Again this is done with simple relative positioning.

The content is moved back into each column

And then finally we chop off the overhanging containers by adding an overflow:hidden; rule on the outermost container - container3.

The unwanted overhanging containers are chopped off with overflow:hidden;

The CSS relative positioning rules

Here is the CSS showing the the addition of relative positioning and the overflow rule. Notice the extra position:relative; on container3, this is to solve an Internet Explorer bug that stops the overflow:hidden; from working.

#container3 {
    float:left;
    width:100%;
    background:green;
    overflow:hidden;
    position:relative;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:30%;
    position:relative;
    left:70%;
}
#col2 {
    float:left;
    width:40%;
    position:relative;
    left:70%;
}
#col3 {
    float:left;
    width:30%;
    position:relative;
    left:70%;
}

Adding padding to the columns

The last thing to do is add padding to the columns so the text is not squashed right up against the edge of each column. If we were to add a CSS padding rule to the columns this might work in some browsers but unfortunately not all. Internet Explorer get's the box model wrong and so it calculates the width of elements with padding differently. A box 200 pixels wide with 20 pixels padding will be a total of 200 pixels wide in Internet Explorer but in all other browsers it will be a correct 240 pixels wide. Padding, you see, should be 'added' to the width of an element, not taken away. CURSE MICROSOFT!

But don't worry... we can solve this problem in a completely different way that does not rely on a padding rule. Instead we just make our columns narrower (the column width minus padding on both sides) and then just move them into the correct position with relative positioning. In our example we will use 2% padding so a column that is 30% wide will be reduced to 26% and a 40% wide column is reduced to 36%. When we move the columns back into place with relative positioning we need to remember that the columns are now narrower so when they are initially all floated together to the left, each one has progressively further to move into place than the one before.

Each content div is moved a different amount because of the padding between them

The completed CSS

To keep the layout together at small widths I have also added an overflow:hidden; rule to each content column. This will chop off any content that is too wide for the column and stop it interfering with the rest of the layout. Again, this is only really a problem with Internet explorer, all other browsers will maintain the correct layout no matter what is in the columns. If you really want to, try exposing this rule only to IE with IE conditional comments.

#container3 {
    float:left;
    width:100%;
    background:green;
    overflow:hidden;
    position:relative;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:26%;
    position:relative;
    left:72%;
    overflow:hidden;
}
#col2 {
    float:left;
    width:36%;
    position:relative;
    left:76%;
    overflow:hidden;
}
#col3 {
    float:left;
    width:26%;
    position:relative;
    left:80%;
    overflow:hidden;
}

Well, that's it. I hope you found this article useful. Have a play with the CSS and see how it works for yourself. You can have as many columns as you want as long as there are the same amount of containers as content columns.


Don't forget to check out my demo pages: 2 column, 3 column, 4 column and 5 column.


Follow me on Twitter @mattjamestaylor

Enjoy this article?

If you find my website useful, feel free to donate any amount you wish. It will help pay for my hosting! =)

Matthew James Taylor

Related articles