How to create a 3-column layout with CSS

One of the most visited pages on this site is the Simple 2 column CSS layout tutorial, where I explain how to create a basic 2-column CSS layout with floats. Many readers have asked for a similar tutorial on how to create a three-column layout, and I’ve been meaning to write one for a few years.

Well, I finally took the time to do it. Three-column CSS layouts have been explained many times, in many different ways, by many people already, so there is nothing (or at least not much) new here. It’s also something that I’m pretty sure that most regular readers can do in their sleep. Regardless, there are many people looking for this info, and it’s convenient to be able to refer to an explanation of how I normally create 3-column CSS layouts with a method that I find robust.

This will not describe a “magic bullet” layout that works no matter which order your content is in the HTML. While being able to switch column order around without changing the HTML makes for a neat CSS demo, it has accessibility issues since it is potentially confusing to people who do not use a mouse when the content order in the HTML does not match that of the visual layout. So I prefer to avoid layouts where the display order is different from the content order.

There are some other related topics that this tutorial does not go into:

  • Making the width fluid or elastic. It’s easy to do, but to simplify this tutorial I’m using pixels for widths.
  • Exactly how the method for clearing floats that I use works – see How To Clear Floats Without Structural Markup for an explanation.
  • Making the columns full-height, either for real or by faking it.

For this tutorial I wanted to focus on the simple task of nesting two-column layouts to create more columns. If you happen to be new to CSS layouts, please read the Simple 2 column CSS layout tutorial first. This tutorial is just an extension of the technique described there.

The HTML structure

So let’s get started. The HTML outline you need for this 3-column layout looks like this:

<div id="body">
    <div id="header"></div>
    <div id="main">
        <div id="content-1"></div>
        <div id="content-2">
            <div id="content-2-1"></div>
            <div id="content-2-2"></div>
        </div>
    </div>
    <div id="footer"></div>
</div>

Here’s what those elements are used for:

  • #body: A container element used to control the overall width of the layout and to center it horizontally
  • #header: A place to put your normal header stuff. It’s not actually part of the 3-column layout, but included here to make the layout a “complete” page.
  • #main: The element that contains the content that will be displayed in columns. No CSS is applied to it in this tutorial, but it often comes in very handy when it’s time to add more advanced styling to your layout.
  • #content-1: The element that will become the left column. This will often be a vertical submenu.
  • #content-2: A container element for the middle and right columns.
  • #content-2-1: The element that will be the middle column. The main content normally goes here.
  • #content-2-2: This element will be the right column, often used as a “sidebar”.
  • #footer: Your footer stuff goes here. Like #header, this is not part of the columns but included for the sake of completeness.

You could argue that the #main and #content-2 wrapper elements are unsemantic and unnecessary, and you would be correct for the most part. However, while there are ways of creating a 3-column layout without the #main and #content-2 wrapper elements, in my experience using these elements makes the layout more robust and the CSS easier to understand. The wrapper elements are also very useful when you’re applying design to the layout. If you leave them out you will often end up having to add them anyway in order to achieve the visual design you want. The only downsides to using them is that they will make the HTML a few bytes larger and that you won’t be able to (easily) rearrange the layout completely without changing the HTML. In my book, those drawbacks are very minor and far outweighed by the benefits.

With that bit of background out of the way, let’s move on to the CSS.

Step 1: The unstyled HTML

Start by taking a look at how your browser renders the unstyled document with a bit of placeholder content added in 3-column CSS layout, Step 1.

Step 2: Overall width and some colours

Now let’s add a bit of basic CSS to make it easier to see what we’re doing. The following makes the entire layout 960px wide and horizontally centered, and gives most of the elements a background colour:

html,
body {
    margin:0;
    padding:0;
    color:#000;
    background:#fff;
}
#body {
    width:960px;
    margin:0 auto;
    background:#ddd;
}
#header {
    background:#fdd;
}
#content-1 {
    background:#bfb;
}
#content-2-1 {
    background:#ddf;
}
#content-2-2 {
    background:#dff;
}
#footer {
    background:#ff9;
}

You can see the results of that CSS in 3-column CSS layout, Step 2. All elements are stacked vertically in a single column.

Step 3: Create the first two columns

To start creating the columns, we’ll use the technique from the Simple 2 column CSS layout tutorial by giving #content-1 and #content-2 widths and floating them in opposite directions:

#content-1 {
    float:left;
    width:240px;
    background:#bfb;
}
#content-2 {
    float:right;
    width:720px;
}

That creates what you see in 3-column CSS layout, Step 3. The #content-1 element now makes up a column on the left side of the page, while #content-2-1 and #content-2-2 are stacked vertically on the right side of the page.

The #footer element looks weird at this stage, but that will be fixed later.

Step 4: Create the nested columns

To turn the #content-2-1 and #content-2-2 elements into columns, all we need to do is repeat what we did in Step 3 – give the elements widths and float them in opposite directions:

#content-2-1 {
    float:left;
    width:480px;
    background:#ddf;
}
#content-2-2 {
    float:right;
    width:240px;
    background:#dff;
}

3-column CSS layout, Step 4 now has the three columns we wanted, with #content-1 to the left, #content-2-1 in the middle, and #content-2-2 to the right.

Step 5: Push the footer down

The #footer element is currently displayed below #content-1, which is not where we want it to be. There are different ways of pushing it down below the three columns, but the most straightforward way is to use clear:both:

#footer {
    clear:both;
    background:#ff9;
}

View the results of that in 3-column CSS layout, Step 5.

Step 6: Clean things up a bit

We’re pretty much done at this stage, but to make the final demo page look just a little bit less ugly, let’s give the main containers some padding:

#header {
    padding:10px;
    background:#fdd;
}
#content-1 {
    float:left;
    width:220px;
    padding:10px;
    background:#bfb;
}
#content-2-1 {
    float:left;
    width:460px;
    padding:10px;
    background:#ddf;
}
#content-2-2 {
    float:right;
    width:220px;
    padding:10px;
    background:#dff;
}
#footer {
    clear:both;
    padding:10px;
    background:#ff9;
}

Note that horizontal padding increases an element’s total width, so to keep the same widths we need to subtract the horizontal padding from the width for each element – #content-1 becomes 220px wide instead of 240px since it has a total horizontal padding of 20px. See Box model in the CSS 2.1 Specification for more details.

As a final touch we’ll also add a class name of cf to some of the elements. This applies a couple of rules based on the technique described in How To Clear Floats Without Structural Markup. Doing this makes the layout more robust since any floated elements added later on will be contained within the elements that these rules are applied to, and it will fix a couple of visual glitches in IE 6 and IE 7.

The elements that we apply the cf class to are #header, #main, and #footer. This will eliminate the need for clear:both on the #footer element, so we’ll remove that as well, leaving us with the final layout in 3-column CSS layout, Step 6.

A simple technique that can create complex layouts

I’ve used this technique for six or seven years to create layouts of varying complexity on many dozens of websites. If you need another column, just repeat the process. If you need a “micro-layout” with columns inside columns, use the same technique there as well.

As I said at the beginning of this tutorial, there are many other ways of creating multi-column layouts with CSS. I have tried most of them, but keep coming back to this. It does the job for me.

Posted on December 16, 2010 in CSS

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.