Pushing the Limits (Part 3): Building a Semantic Four-column CSS Layout

July 22nd, 2008 in Design Tips & Tutorials

by: Matthew Griffin

In part two of the Pushing the Limits series, we looked at some simple techniques for building a four-column CSS layout. Unfortunately, the divide and conquer method we explored (although quick and easy) leaves something to be desired in the area of semantic markup. Now, we'll consider another solution that uses a little Javascript to make up for the shortcomings of CSS.

Setting Up the Markup

The example we will be looking at uses a combination of relative and absolute positioning to place columns where they are supposed to go. We'll start out with some good semantic XHTML markup for our layout and then we'll jump right into the CSS. Here's the 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>

You might recognize this markup from the example in the previous article. It's the semantic markup that we wanted to use so badly, but CSS wouldn't let us. Now, we'll take another stab at it.

Forcing Columns into Position

You're probably familiar with float: right and float: left, but for now we're going to set those attributes aside. Instead, we will be using position: absolute and position: relative to get the job done. We'll start by setting all of our columns to the same width and all but one of our columns to position: absolute. If you've been working on websites for awhile you've probably used absolute positioning to set elements to a position relative to the entire page. However, by setting our wrapper <div> to position: relative, all of its contained absolutely positioned <divs> will be positioned relative to the wrapper <div>.  We'll set one of our columns to position: relative so that our wrapper <div> will expand properly and push the footer content down below the columns. If we were to position all of the columns absolutely, the footer content would appear mixed with the columns (or behind the columns). Check out the live example if you need to. 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;
    position: relative;
}

#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;
}

#column1, #column2, #column3, #column4 {
    width: 173px;
    border-right: 1px solid #ccc;
}
#column1, #column3, #column4 {
    position: absolute;
    top: 59px;
}

#column1 {
    left: 0;
}
#column2 {
    position: relative; /* Sets column2 to push the footer down where it should be */
    top: 0;
    left: 195px;
}
#column3 {
    left: 390px;
}
#column4 {
    left: 585px;
}

You'll notice that we had to set the "top" attribute to 59px on all of our absolutely positioned columns. Without this attribute set, these columns would appear at the top of the page where their parent <div> "wrapper" begins. The relatively positioned column doesn't require this attribute. You could also set your header height to 39px to avoid problems with visitors who have their text size set higher or lower than normal.

One Little Problem

This method works great as long as the content in the relatively positioned column  (In this case column2) is longer than the content in all the other columns. There are many cases where this won't pose a problem at all. As long as you know which column will be the tallest, everything will work fine. But on websites with dynamic content where the tallest column is constantly changing, you'll be in for some funky layout problems. This is where Javascript comes to the rescue.

All we have to do is set a script in our page that checks for the tallest column and then sets the relatively positioned column to that height. Sounds easy enough. Here's a Javascript function that will do the trick.

function setColumns() {

if (document.getElementById) {
var layoutColumn = new Array();
layoutColumn[1] = document.getElementById("column1").offsetHeight;
layoutColumn[2] = document.getElementById("column2").offsetHeight;
layoutColumn[3] = document.getElementById("column3").offsetHeight;
layoutColumn[4] = document.getElementById("column4").offsetHeight;

tallestColumn = layoutColumn[1];
    for ( var i = 2; i < layoutColumn.length; i++ ) {
       if ( layoutColumn[i] > tallestColumn) {
          tallestColumn = layoutColumn[i];
       }
    }

document.getElementById("column2").style.height = tallestColumn + 'px';

return true
}
}

To make the funciton run, just put an onload call in your opening body tag that looks like this: <body onload="setColumns()">. Now, I realize that there are probably some great Javascript programmers out there that could improve this function, but this will accomplish the task. The whole thing can be seen in action here. A List Apart also has an article about a similar solution that I highly recommend.

  • 23 Comments
  • 14878 Views

Comments

Posted By: Wes P on 07/22/08

That's cool that this works, but I would likely not recommend any layout that relies on javascript to render properly. I'm of the javascript mindset which believes that your site should be functional to the end user BEFORE javascript is added to the page. This addresses certain SEO and accessibility issues common to today's sites that use javascript for everything. It also insures that anyone browsing with javascript off or the NoScript Firefox extension installed will be able to see your site properly. Thanks for the article Matt!

Posted By: andymurd on 07/22/08

I was with you right up until the javascript. I agree with Wes that a design should work without javascript. Have you tried A List Apart's faux columns technique with your four column layout? It requires a few extra DIVs but should eliminate the need for scripting.

Posted By: Matthew Griffin on 07/22/08

Thanks for the comments. Yes, I read A List Apart's article on faux absolute positioning and I loved it. It's definitely one of the best methods I've seen yet. The good thing the particular method I described above is that it actually works without javascript as long as your relative column is the longest. The javascript is just a fall-back. It degrades pretty gracefully as far as four column designs go.

Posted By: Edgar on 07/22/08

Matt, I like this series you've started. I don't know what your plans are, or how much you want to add to this example: Other things would be: Adding boxes to the columns. Boxes to be used for quotes, or menu sections, etc. One of the layouts I want to get for our site is the grid one, or something that looks like it. Yesterday, I came across this one: http://www.wdavidphillips.com/ I really, really like it. my next re-design will look like his.

Posted By: Matthew Grffin on 07/23/08

Edgar, this is probably the last of the articles I will write in this particular series. But I like your idea about writing a tutorial on building flare elements. I'll try to put something together for the future.

Posted By: Hans on 09/02/08

I was inspired by Matthew James Taylor's perfect multi column liquid layouts(http://matthewjamestaylor.com/blog/perfect-multi-column-liquid-layouts) and developed a online tool to generate multi-column layout,incl. 4 column. There's no need to use javascript. If there's need, it's also possible to design a 5 column layout generator. http://www.pagecolumn.com/4_col_generator.htm

Posted By: Laura on 02/13/09

Fortunately I am creating an area of tabular data. This means all of my columns are the same length. Thank you for this. I looked at two other sites and tried to reproduce the code correctly and couldn't. Newbs need help most!

Posted By: Matthew Grffin on 02/13/09

Glad it helped, Laura.

Posted By: Juhani on 04/01/09

Nice work Hans. Especially liquid four column layouts are fine. I think very many are looking for liquid four column layouts, where the leftmost and rightmost colums are fixed (e.g. for menus, contact infos and ads) but two middle colums are fluent (for main content). Everything goes well until looking them on IE6... I agree that Matthew James Taylor's three column layouts are perfect. Easy and perfect.

Posted By: Clubturk.net-2. Seo Yarismasi on 04/27/09

That's cool that this works

Post Your Comment

Comments are closed.