CSS: Faux Columns - How to Get Equal Height Columns Regardless of the Content Size?

Multi-column layout is still a very trendy way of structuring a website. Along with a top header and bottom footer, you usually see three columns - a left one representing a main sidebar with vertical menu, a middle one for the most important content and a right one for miscellaneous things. Usually the amount of content in each of these columns vary significantly. Assuming you want to give a different background colour for each column, making them all have equal height can be a challenging task.

The Problem

The following screenshot shows what we are talking about here. We have a typical centered (margin: 0 auto;) layout with fixed width of 980px. Left column is 280px, middle one is 500px and right one is 200px.

As you can see only the middle column is able to reach to the footer due to the biggest volume of content within. We want all the columns to have the same height.

Source code representing the problem looks like:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Faux Columns</title>
    <style>
        body {
            background-color: #dadada;
            color: #000000;
            font-family: Arial, serif;
            margin: 0;
            padding: 0;
            line-height: 30px;
        }

        div {
            padding: 10px;
            box-sizing: border-box;
        }

        #wrapper {
            width: 980px;
            margin-left: auto;
            margin-right: auto;
            padding: 0;
        }

        #header {
            background-color: #bababa;
        }

        .column {
            float: left;
        }

        #left {
            background-color: #ff453a;
            width: 280px;
        }

        #middle {
            background-color: #ffd60a;
            width: 500px;
        }

        #right {
            background-color: #30d158;
            width: 200px;
        }

        #footer {
            background-color: #bababa;
            clear: both;
        }
    </style>
</head>
<body>
<div id="wrapper">
    <div id="header">
        Header
    </div>

    <div id="left" class="column">
        <?php foreach(range(1, 10) as $i) { ?> Link <?php echo $i; ?><br /> <?php } ?>
    </div>

    <div id="middle" class="column">
        <?php foreach(range(1, 20) as $i) { ?> Content <?php echo $i; ?><br /> <?php } ?>
    </div>

    <div id="right" class="column">
        <?php foreach(range(1, 5) as $i) { ?> Other <?php echo $i; ?><br /> <?php } ?>
    </div>

    <div id="footer">
        Footer
    </div>
</div>
</body>
</html>

Let's briefly go through the HTML structure. All visible elements (header, footer and three columns) are wrapped by a parent element called #wrapper. Wrapper's width is a sum of widths of all the columns. We give each column a shared class name (.column) which is responsible for positioning (float: left;). Finally we add cleath: both; to the #footer to place it underneath.

The Solution

The way we approach the problem is quite interesting as we simply remove background-color property from #left, #middle and #right. Instead we are going to prepare a background image. We need a thin PNG slice which is going to be 980px wide and only 1px high.

Now going pixel by pixel from left to right:

  • pixels from 1 to 280 should be coloured with #ff453a
  • pixels from 281 to 780 should be coloured with #ffd60a
  • pixels from 781 to 980 should be coloured with #30d158

In other words, each range of pixels should match the colour of a column they are going to imitate and "imitate" is the key solution here as we apply this background image to the #wrapper (parent) element. The trick here is to use background-repeat: repeat-y; so that the slice is going to be repeated horizontally (Y-axis) to give an illusion of faux columns.

This is our background slice (aspect ratio of the image has been changed for easier preview). Save it as PNG instead of JPEG to avoid any compression blur between colour shift.

Now let's see styling for the #wrapper element:

#wrapper {
    width: 980px;
    margin-left: auto;
    margin-right: auto;
    padding: 0;
    background-image: url('faux_column.png');
    background-repeat: repeat-y;
    background-position: 50% 0;
}

The result is presented on the following screenshot:

This is it. Optically all three columns have "equal height". This trick makes the entire layout more consistent and less incoherent. Keep in mind that this solution is suitable only when we deal with a fixed-width wrapper. I hope you find this solution creative anyway.

Side note revision

Originally I wrote this article in 2006. These days the Faux Columns solution may not look as impressive as it was back then. Today there are frameworks like Zurb Foundation or Twitter Bootstrap. Also developers are not prudent when it comes to use tons of JavaScript to solve bunch of issues like this one. Yet I still find the solution quite valuable.

As a small refresh of this content, new screenshots have been made as well as box-sizing: border-box; property has been added to the generic div element for easier width calculation (back then we could only dream about little goodies like this one in CSS).


Last revision 2021-11-23 15:10:16