Pushing the Limits (Part 2): A Simple Four Column CSS Layout with a Little Divitis

July 14th, 2008 in Design Tips & Tutorials

by: Matthew Griffin

CSS works very well for designing one and two column layouts. It's shaky but workable on three-column layouts. But if you want a four column layout, you have to get downright creative. This article presents an easy, straightforward method for designing a four-column CSS powered layout without deviating too far from the semantic model. Granted, Jeffrey Zeldman would accuse me of a slight case of divitis but at least this method doesn't revert to tables or improper use of unordered lists.

Why CSS Chokes on Four-column Layouts

I explained the basic issues involved with CSS and the 3+ column layouts in my previous three-column tutorial, but you'll need some additional information as we move from three columns to four. The most basic issue we face is that CSS only has two attributes that affect horizontal alignment of block-level content: float: right and float: left. We can simulate a three-column layout by floating one box to the right, one to the left, and letting the third box slide up the middle. But that's about as far as that method will take you. CSS3 will have built-in support for multiple columns, but for now (and probably for quite awhile) we'll have to make do with what we have. Before we get started, though, here's a link to the example below in action.

Setting Up the Markup

I'm going to start by giving an example of how the markup should look in a perfect semantic universe. Then we'll add in the extra markup to make the layout work the way we want it to. As you will see, the difference is minor and, in my opinion, worth the sacrifice. Here's the Utopian markup:

<div id="wrapper">

    <h1 id="header">My Personal Homepage</h1>

    <div id="column1">
       Column One Content
    </div>

    <div id="column2">
       Column One Content
    </div>

    <div id="column3">
       Column One Content
    </div>

    <div id="column4">
       Column One Content
    </div>

    <div id="footer">
       Come back again soon
    </div>

</div>

Wow! So beautiful, so simple. This is how we should be able to mark this page up. Unfortunately, it just won't work. As I explained, CSS has no attribute for multiple columns, making the perfectly structured markup above ineffective. Now, we'll soil it with some additional <div>s and make it comply.

<div id="wrapper">

    <h1 id="header">My Personal Homepage</h1>

    <div id="section1">

        <div id="column1">
           Column One Content
        </div>

        <div id="column2">
           Column One Content
        </div>

    </div>

    <div id="section2">

        <div id="column3">
           Column One Content
        </div>

        <div id="column4">
           Column One Content
        </div>

    </div>

    <div id="footer">
       Come back again soon
    </div>

</div>

The only difference between this markup and the markup in the first example is the addition of two <div> tags. We now have columns one and two wrapped in a <div> called "section1", and columns three and four wrapped in a <div> called "section2". It's not the best case scenario, but we haven't fallen too far off the semantic path and, of course, the markup will still validate.

Rightly Dividing Two Columns into Four

Now it's time to style our markup with a little CSS. We'll start by giving our container a set width to hold the rest of our layout together. Then we'll float our two section <div>s to the left and right inside the container. This will effectively give us two columns, each containing two nested <divs>. Next, we will float each of our nested columns ("column1", "column2", etc.) to the right and left inside their respective containers. When we're finished, we will have a full-fledged four-column layout. Here's the CSS:

body {
    font: 1em Verdana, Arial, Helvetica, sans-serif;
    background: #ccc;
    color: #000;
    text-align: center; /* Centers the container */
    margin: 0;
    padding: 0;
}

#wrapper {
    width: 780px; /* 780px is just wide enough to fill and 800px screen */
    margin: 0 auto; /* It's important to set the margin to auto if you want the layout to center */
    background: #fff;
    text-align: left;
    border: 1px solid #999;
}

#header, #column1, #column2, #column3, #column4 ,#footer{
    padding: 10px;  /* This sets a 10px padding on all of our content boxes */
}

#header {
    background: #999;
    margin: 0;
    padding 0;
}

#section1 {
    float: left; /* Sets this section to the left */
    background: #fff;
    width: 385px;
}

    #column1 {
        float: left; /* Sets this column to the left inside its section */
        background: #ccc;
        width: 167px;
    }

    #column2 {
        float: right; /* Sets this column to the right inside its section*/
        background: #ccc;
        width: 168px;
    }

#section2 {
    float: right; /*Sets this sectionto the right */
    background: #fff;
    width: 385px;
}

    #column3 {
        float: left; /* Sets this column to the left inside its section */
        background: #ccc;
        width: 167px;
    }

    #column4 {
        float: right; /* Sets this column to the right inside its section*/
        background: #ccc;
        width: 168px;
    }

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

As I mentioned above, you can check out a live working example here. I've placed the CSS in the <head> to make it easier to read.

It Works... So What's the Problem

We've done it—a perfectly symmetrical four-column CSS-powered layout. The problem with this approach is that we are fusing style with content. If, for example, we ever want column1 to be where column4 is, we will have to make changes to the markup; whereas we should be able to make this change in our CSS file alone. But such is life. In the third part of this series, we'll take a look at a solution that uses more properly structured XHTML combined with a little Javascript to accomplish the same thing.

  • 107 Comments
  • 29652 Views

Comments

Posted By: Wes P on 07/15/08

Are there pitfalls with using 4 divs all float: left? Or are there IE issues as is usually the case? I worked up a quick test and everything seems to render correctly, however my test wasn't any more rigorous than a few characters per column. I suppose you still have the issue with not being able to reposition the columns without changing the markup itself. Alternatively, you could use absolute positioning, however if you wanted a footer, you're up a creek. On a different note, I am quite excited about the CSS3 specs, and can't wait to use them. I can only hope browser makers get in gear to support as much as possible, as quickly as possible so that in a few years it'll be acceptable practice to use it.

Posted By: Matthew Grffin on 07/15/08

Wes, actually I like the left floated div method. And it does work in IE6. You are right, though, that you still have the problem of having to go to the markup to change the layout. With the method above, you are at least able to move the columns within their respective sections without going to the markup. In part three, I'll be presenting another method that gives even more layout control to the stylesheet. Also, A List Apart recently published an article called Faux Absolute Positioning that I think may be the best method I've seen to date.

Posted By: Matthew Griffin on 07/23/09

Great! Glad I could help, VTC.

Post Your Comment

Comments are closed.