Please note that you may have been redirected (you might like to make a note of the URL in the address bar of your browser and update accordingly) This is a permanent archvie but is no longer actively maintained. Please visit http://joshuaink.com for the latest updates.

A simple introduction to 3 column layouts

Saturday March 5, 2005

This was not something I had intended to post on my blog, it was originally written for a friend who is heavily into multi-media and wanted a quick insight into standards based design. It ended up being a lot bigger than I had anticipated and so I have decided to post it here incase someone else finds it useful.

Disclaimer

This tutorial is by no means complete and is intended as a quick 'how to' guide for beginners rather than a definitive guide to why these things work (or in the case of older browsers, don't work). For the sake of simplicity I have chosen fixed width rather than fluid design, though these methods can easily be used as the basis for fluid layouts.

If you want to follow along, you can download the sample pages (.zip) and simply edit the CSS file as we move along.

Browsers

You should use a modern browser to view the demos, such as Firefox (PC or Mac) or Safari (Mac) but have a copy of Internet Explorer 6 at hand.

A note about Internet Explorer 5

Update
I have since added some notes for IE 5 and they can be found here.

Whilst writing this tutorial I ran into the inevitable problems with IE5 on both Mac and PC, in the end I decided to pull support for IE 5 on both platforms (with the exception of the centering on screen workaround). It wasn't a decision I took lightly, but I had to focus on what this tutorial is all about, trying to demonstrate to someone who is brand new to standards that it isn't that difficult to do. Some may argue that in doing so I am only telling half the story, and they would be right, you will at some point have to deal with the problems this browser can throw at you. Personally, I think that when you are having your first crack at a standards based layout it is much easier to deal with neat, tidy, hack free CSS and ditching IE 5 affords us that luxury. If hacks are what you want, this is not the tutorial for you.

Take some comfort in the fact that the problems I did run into were not that difficult to put right and there is plenty of information out there on how to fix them. I have provided links to further reading throughout the tutorial in the hope of helping you to fill in the gaps and answer any questions you may have. Let's get to it...

Page structure

HTML semantics are often the subject of heavy debate, what I am going to show is my current preferred way of setting up a page. At this early stage, what is more important is that we are not going to change the HTML of this page, even though we will produce four different layouts.

But why is it important that we don't change the HTML, you may ask? Well, a lot of people new to web standards (me included) will move the HTML around to make it a little simpler to get the desired visual results, and sometimes when creating a really complex layout, this can't be avoided. The ideal, however, is that the HTML should not influence the way the page ends up looking, at all, that is the supposed to be the job of the CSS. It is a good habit to get in to from the offset.

Before we move on to the styled examples you might like to take a look at the page used throughout in it's raw state.

From looking at this raw HTML page it is difficult to see how we are ever going to get any kind of design going. So, have a quick look at this lightly styled example.

You will see, highlighted in grey, five main divs each which it's own unique ID, #header, #sub-content etc. Surrounding all of these divs is the #wrap div, highlighted with a dotted grey border, and it's two purposes in life will be firstly to place our site at the center of the screen and from there on to serve as the 'parent' to our other five divs. All of these divs can be considered has having zero 'value' in terms of the content of the page, they are only there to allow us to modify the layout as we wish; think of them as the replacement for the table cells you may be used to using for layout purposes.

Skip links

Before we start on any of that the real layout work, let's take a quick look at a couple of odd looking links found throughout the page, those being the 'skip' links.

To help me explain the purpose of these links I have given the headings on the page a little more meaning, take a look at this example headings page, the headings are highlighted in red, the skip links in bold blue.

We provide these links for people who may be using a screen reader, or a text only browser, such a Lynx, and they are designed to make navigating the page, without the obvious benefits of a graphical user interface and/or a mouse, that much simpler.

Common sense usually dictates where these links are placed on the page, for the purposes of this demonstration I have included three sets for discussion.

The first of these links is provided directly after the main content heading (in the example 'The meaning of life') and that is a strategic placement, allowing the user to gauge roughly what the page is all about before deciding whether they want to read the content on that page or go straight to the navigation sets and look for something else.

The second 'skip to navigation link' occurs in the Elsewhere section and on this occasion I have placed the link directly after the paragraph describing the contents within this section. The reason for this placement is pretty self-explanatory , it is used to help orientate the user before they decide whether they want to read the contents of that section or move on. In this instance I chose to provide a explanatory paragraph because the heading isn't 100% clear about the contents of the section.

Finally we reach the foot of the page, a dead end essentially, and so we offer the user two choices, go back to the navigation or read the contents of the page by jumping back to the top of the page.

There are obvious flaws even with this simple example, I haven't provided any opportunity to skip straight to the Elsewhere section. Okay, I admit it, maybe I am being a little manipulative here, maybe I don't want my site visitors going elsewhere until they have at least had a little look around or read one page of content!

The general rule is use your common sense and keep in mind that you can easily add more of these links at a later date if you see the need.

For the purposes of this tutorial, we are going to hide these links from visual browsers with good CSS support, but it is worth noting that if the design can cope with it, leave them visible, this will only serve to improve accessibility, especially for those using the tab and return keys to navigate the site. One nice example of a page that has kept a skip link in place is Hicks Design, where Jon incorporates his 'skip to content' into the overall layout of the site.

If you want to get a feel for how these links work, put down your mouse and use the tab and enter key to navigate the example headings page.

The HTML code sample below shows the skip link contained within a paragraph and it has been assigned a class 'hidden-navigation'. All instances of skip links are assigned this class.

  1. <p class="hidden-navigation">
    <a href="#navigations" title="Jump to the main navigation">Skip to navigation</a>
    </p>

In the case of the foot links, which use an unordered list rather than a paragraph, we simply apply the class thus:

  1. <ul class="hidden-navigation">
  2. <li><a href="#navigations" title="Jump to the main navigation">Skip to navigation</a></li>
  3. <li><a href="#header" title="Jump to the top of the page">Top of the page</a></li>
  4. </ul>

Note: We use a .class rather than an #ID because the rules dictate that we can have multiple instances of a .class on a page but an #ID must only ever occur once on any single page.

Headings for sections

Finally, before we go ahead and hide these links I just want to go back to the headings used for each div. Again to the example headings page and you will see that each div has a heading which broadly describes it content, and these are another aid to accessibility. Common sense tells us that a heading distinguishes one div (or section if you like) from another, much like a chapter title in a book. Although we want to leave all of the headings in place, I would like to hide a couple of them as they are not really needed for our purely visual display. We will apply the same method to these headings as we will to the skip links.

Note: The correct use of headings is a bigger subject than I want to discuss here and so I recommend you read Andy Budd's article, heading elements semantics and the spec (read the comments as well).

The CSS that follows describes a method of shifting the skip links, and headings we want to hide, off to the left of the screen. This is used rather than the more obvious 'display:none;' rule because some screen readers aren't advanced enough to allow us to easily make the distinction between it (the screen reader) and a normal visual browser. There is a full discussion about this over at CSS-discuss. So, let's just get on and apply the CSS to the page:

  1. .hidden-navigation,
  2. #navigations h2,
  3. #foot h2{
  4. width:1px;
  5. position:absolute;
  6. left:-9999px;
  7. }

That's it, and now if we look at our example, the skip links and main headings within the #navigation and #foot divs have vanished. Time to get on with the fun stuff.

Grey box layout

A grey box layout done in your favourite graphics package is a good way to start with any website (hat tip).

I usually mock up the basic layout of the page and do the maths before I even touch any code. This can be a particularly useful visual aid if you are making the leap from working in a WYSIWYG environment. Here is the grey box layout I started with for this tutorial

Center on the screen

First off we are going to center our design on the screen and to do this we add the following CSS:

  1. #wrap{
  2. width:770px;
  3. margin:0 auto;
  4. }

We have used a 770px width so that the site works at a minimum resolution of 800 x 600. The margin setting above is CSS shorthand and it is telling the browser to apply no margins to the top and bottom of the div but to apply auto margins to the left and right. For most modern browsers, that's all we need to do (see example) but then there is the slight problem of Internet Explorer 5, which ignores the rule. To cure IE 5 we apply the following CSS to the body:

  1. body{
  2. text-align:center;
  3. }

As our example shows this has now centered the site in the middle of the screen when viewed in IE 5, but it has also centered all the text. To fix this we need to modify the CSS applied to #wrap, bringing the text back over to the left hand side:

  1. #wrap{
  2. width:770px;
  3. margin:0 auto;
  4. text-align:left;
  5. }

Job done, our text is where it should be (see example) and we can now move on from the #wrap div, it's job is done.

Float it

Floating divs is not the only way to position content on a page, but I personally find it the easiest to apply quickly. I will explain the reasons why a little further on down the page, but for now let's get on and set up our basic floated layout.

First job is to apply widths to each div and referring back to our grey box layout we can see what's what:

  1. #main-content{
  2. width:400px;
  3. }
  4. #sub-content{
  5. width:175px;
  6. }
  7. #navigations{
  8. width:175px;
  9. }

With this done (see example) we simply need to apply the floats and add some margins to push them apart slightly:

  1. #main-content{
  2. width:400px;
  3. float:left;
  4. }
  5. #sub-content{
  6. width:175px;
  7. float:left;
  8. margin-left:10px;
  9. }
  10. #navigations{
  11. width:175px;
  12. float:left;
  13. margin-left:10px;
  14. }

The foot

If we take a quick look at our example we can see that things aren't quite right, the foot is not where it should be, at the bottom of the layout. This is the main reason we are using floats rather than any other method, because it is really simple to fix this problem by applying the following to the #foot div:

  1. #foot{
  2. clear:both;
  3. }

As the example now shows the foot is stuck to the bottom of the layout and it it will continue to happily stick to the bottom of the layout no matter what the length of the content in the three floated divs above it.

As I said, there are other ways to layout a page with CSS and one of the most common is using the 'position:absolute' rule. This method is beyond the scope of our gentle introduction, but in terms of getting the foot to stick to the bottom of an absolutely positioned layout, life gets a little more complicated. All I am going to tell you is that you will need a touch of JavaScript to achieve the same results as the floated method. Luckily for us, this can be found in the form of Shaun Inman's Absolute clearance script. Web standards people are just the most generous souls I tells ya!

A quick note on #header and #foot

You will notice that we haven't set any widths for the #foot and #header divs and it isn't really necessary as their defaults are set to 100% by the browser, hence the reason you can see them stretching the length of the #wrap div. If it makes you feel more comfortable you can set the width to 770px, it will do no harm.

The other thing to note is that in Internet Explorer and Firefox, the top and bottom margins of these two divs differ somewhat when compared. This is caused by differences in the default browser settings (or inbuilt CSS if you like). I don't want to go into any detail here, it will only distract from the main purpose of this tutorial. For more information on ways to tackle this issue you might like to read Richard Rutter's Resetting default padding and margin article.

Sidebars to the left of #main-content

Our basic floated layout is done, easy huh? But what if we want the #navigations and #sub-content to the left of the #main-copy? That's actually very easy too, simply change all instances of 'float:left;' to 'float:right;' and change all instances of 'margin-left:10px;' to 'margin-right:10px;' (see example)

Centering the main content

Now that you have seen just how simple it is to create a layout using floats, you're probably starting to think about moving things around a little. For example, we might like the #sub-content div to the left of #main-content, and it is usually at this point that you might think about tinkering with the HTML, but there is no need thanks to the magical mystery that is negative margins.

Shifting the #sub-content to the left

Important: Revert back to the original 'float:left;' layout before trying this out.

We will look at why this works in the next example but for now, let's just do the practical exercise.

First off we want to shift our #main-content div over to the right leaving enough space to it's left for the #sub-content div to sit with a ten pixel margin to the right. We know #sub-content is 175px wide so the maths is pretty simple, our negative value is calculated by adding the width of #sub-content to the 10px margin. The CSS is as follows:

  1. #main-content{
  2. width:400px;
  3. float:left;
  4. margin-left:185px;
  5. }

This example shows the effect this has had, we're 50% of the way there. The #sub-content div now needs to be pulled to the left hand edge of the #wrap div. To do this some more simple maths is needed. To get our negative value we add the width of the #main-content div (400px) to the width of the #sub-content div (175px) plus the 10px margin we want between the two. The CSS is as follows:

  1. #sub-content{
  2. width:175px;
  3. float:left;
  4. margin-left:-585px;
  5. }

see example of the finished results.

Shifting #navigations to the left

Shifting the #navigations div to the far left of the page is essentially the same as the method described above but the maths are a little different and it gives us a chance to look, in practical terms, at how floats work.

Referring back to our lightly styled example we can see that the #navigations div is last in the pile of three that we have floated, and this is reflected in our simple 'float:left;' layout shown in this example, where the #navigations div ends up on the far right of the page.

What this shows us is that when floating a layout, the floated elements are related to each other and each has an effect on the other. Again, we can see this in action in the example where we shifted the #main-content div to the right, it (#main-content) pushed #sub-content to the right which in turn pushed #navigations to the right and because the #wrap div is only 770px wide, #navigations ran out of horizontal space, and so it 'wraps' to the next line (You've heard the nursery rhyme, there were ten in a bed and the little one said roll over, right? Think of #wrap as being a bit like the bed.).

Just to complicate matters a little further, because the #main-content div contains a lot of copy the #navigations div gets 'jammed' on the right hand side of the page. If the #main-content was a little shorter then the #navigations div would shoot right back over to the left hand side of the page (That's what it's been trying to do ever since we told it to 'float:left;', so we can't really blame it now can we.). Confused? Good, me too, let's just get on with the good stuff shall we?

We proceed as before (example) shifting the #main-content div over to the right to make space for our #navigations div to sit on the left of it:

  1. #main-content{
  2. width:400px;
  3. float:left;
  4. margin-left:185px;
  5. }

This time though, we don't need to touch the #sub-content CSS and it should be left as follows:

  1. #sub-content{
  2. width:175px;
  3. float:left;
  4. margin-left:10px;
  5. }

This is where things are different from our first example, and as explained above, we need to get past both the #main-content and the #sub-content because in the relationship #navigation is at the bottom of the pile. The maths is actually really simple, the #navigation is last in the pile and now we want it to come first. To do this we simply set the negative margin to the width of the #wrap div and in so doing bring #navigation's left edge flush with #wrap's left edge;

  1. #navigations{
  2. width:175px;
  3. float:left;
  4. margin-left:-770px;
  5. }

See the results .

Another grey box

Negative margins are a little confusing, so to try and help visualise how it all works I prepared another grey box layout illustrating how we shifted the #navigations div to the left.

The IE Doubled Float-Margin Bug

Surely it can't be that simple? Well, no it can't, and as soon as we started seriously messing around with margins in a floated layout, it was inevitable that Internet Explorer would rear up and bite our asses. If you open up our example in Internet Explorer 6 you will see our little trick has not worked, in fact it's a total mess, oh my!

Fortunately their is a solution to this double margin bug, and it's really simple. I don't want to go into detail here, the nice people at PIE have already done that. Let's just get on and apply the fix:

  1. #main-content{
  2. display:inline;
  3. width:400px;
  4. float:left;
  5. margin-left:185px;
  6. }

With the 'display:inline;' fix applied, the layout now works in Internet Explorer. Open up our example in IE 6 once again to see it in action. So you see IE can be a mean mistress, but she's not so bad when you learn how to handle her.

Further reading

That's about it, I hope it is has been useful. Above are links to articles I think are particularly relevant to helping you move forward from what we have touched upon here. Good luck!

  1. Rob Mientjes

    1832 days ago

    Like I told you, excellent write-up. I hardly see them as good as this one. And that might sound like a compliment, but it’s actually just a critique on others ;)
  2. Jeff Smith

    1832 days ago

    Excellent article John. I’ve actually been toying around with the idea of adding a third column to my layout to accomodate some extra info. I now definitely know that I’m on the right track with the markup that I’ve got written down in my notebook, so implementation should go a lot faster.
  3. David Bisset

    1832 days ago

    Great article… going on my linkblog (davidbisset.com).
  4. Eric Irvine

    1832 days ago

    Excellent article, newcomers to css will inevitably come across this and smack their foreheads, that’s how!, being relatively new I learned some too, I would’ve used display:none on the skipnav but the negative positioning way is much better.
  5. Hans

    1831 days ago

    Wonderful article. This’ll come handy when I’ll “undesign” my blog… 4 columns, one for each post on the front page. Thanks for the great info!
  6. Tom Werner

    1831 days ago

    Great writeup, John. Once fully comprehended, floats are a godsend and I find myself using them more and more to make my web design life easier. And now that I’ve realized the power (thanks to you!) of overflow:hidden, no more tears!
  7. Malarkey

    1831 days ago

    Nice one John. Just blogged it at www.stylegala.com!
  8. Lou

    1831 days ago

    This is great. One of the best tutorials I have ever read. Great job!
  9. Hashim

    1830 days ago

    “Whilst writing this tutorial I ran into the inevitable problems with IE5 on both Mac and PC, in the end I decided to pull support for IE 5 on both platforms”

    That’s when I stopped reading.
  10. Jolo

    1830 days ago

    Easy to follow…. functional, great…
  11. Thomas

    1830 days ago

    Excellent article on layouts. Easy step by step instruction.
  12. Mehmet

    1830 days ago

    John,

    It is a great article. Easy to read, easy to follow. Great job.

    I am looking forward to your future articles.
  13. David Laakso

    1830 days ago

    Nice job!
  14. Mohsen

    1830 days ago

    l;;;l;
  15. Calle

    1829 days ago

    Thanks for the very nice article, but can’t you, please, place the css within the html-documents?
  16. J??rgen Brostr??m

    1828 days ago

    Great article! It’s been said before, I know, but your article is really easy to follow and understand. Excellent work!
  17. Daniel

    1827 days ago

    Pretty well written tutorial. May I ask a question?

    Is it possible to change the CSS so that #main-content will float around #sub-content and uses the full page below of #sub-content?

    How would one do this? Thanks in advance.
  18. Daniel

    1827 days ago

    No, that was exactly what I had in mind, the L form describes it best.

    In this is only possible with more divs, then well… any pointers where I might find out how create the L form?
  19. Daniel

    1827 days ago

    Thanks John, that did the trick.
  20. Venkat

    1826 days ago

    Just what I was looking for. Google ranked it first on my search. Fantastic write-up. Great job, John. Doesn’t get much better than this.
  21. Mark Joint

    1826 days ago

    We’re just getting our heads round coding everything ‘properly’ using css and neat html – really useful article.

    One question – the IE fix for the double float margin – great in IE6/win, but is there any chance you know of anyway to get round the problem in IE/mac?!

    or is this browser (IE/mac) not one I should consider worth worrying about now safari is on the scene?
  22. corey

    1826 days ago

    After adding the floats to your example file, I notice that there is a pixel or two drop in-between the floats. When i added

    div {
    margin: 10px 0 10px 0;
    }

    it rendered properly. Why is this?
  23. Andreas

    1825 days ago

    I’m still developing my skills with CSS – meaning that although not entirely new to it I feel like a newborn every time I read an article like yours: it’s all wow! and oooh!, and I am motivated over and over to design according to the standards.
    Great work! Am looking forward to more!
  24. Brad

    1824 days ago

    If anyone wants to use it in IE 5.x/Win, wrap the 3 columns in a single extra wrapper div#wrapper, and use the following CSS to get it to work:

    #wrapper {
    width: 770px;
    float: left;
    background: transparent;
    margin: 0;
    }
  25. Brad

    1824 days ago

    Before I sound like I’m being critical, I should clarify that John’s article above is an excellent article – especially for those new to CSS. My fix above should help those designers who are unwilling (or unable) to drop support for that old warhorse IE5.x/Win.

    Of course, you should look at the user base of your website before deciding which browsers to support/drop. :)
  26. Jay

    1824 days ago

    Having a small issue with this design. I set the “Navigations DIV” margin to the negative setting of -770. Works great in IE and lines up within the wrapper DIV. However; when viewing the page in Firefox or Netscape, the Navigation Float shoots this off the screen to the left and cuts off the view. FYI, I am not using margins to set the space between Columns. I did a 200px,370px,200px for the 770px (to match the wrap width). Is there a fix for this issue? I am thinking something is off in the CSS coding.
    The layout to view is at: http://www.petsfoundation.org/tryagain.html
    CSS file location: http://www.petsfoundation.org/css/trynew2.css

    Any help would be greatly appreciated..
    Thanks,
    Jay
  27. Jay

    1823 days ago

    Fixed the issue.

    Math and HTML was coded wrong. Looks like this design is going to work. I really wanted to get away from absolute positioning. Great write up on this layout.. Thank you!!
  28. Kenny

    1822 days ago

    Great article!

    Something I notice that IE 6 does, is, when trying to view the layout in full-screen view, it extends the center col out over and below the footer. For some reason, applying overflow-hidden doesnt work either.

    many tks :)
  29. Pixelpusher

    1822 days ago

    Great article. This surely solves a lot of issues in an elegant way.
  30. Allen Leff

    1821 days ago

    Hi,

    I am new to this, sorry for not understanding.

    Is it too much to explain in plain talk about the hidden-navigation and its use?

    Thanks in advance
  31. Louis Proyect

    1813 days ago

    I am a computer programmer with 37 years in the field. For the past 4 years or so I have been developing Intranet applications for Columbia University using Java. I have also used Perl/CGI and PHP there.

    I have had my own website for at least 6 years that uses tables for layout. I am trying to redesign it using CSS. I am about to tear my hair out getting it figured out. Until the people responsible for implementing CSS can make it a lot easier to put together 3-column pages, which I am trying to do now, people will still use tables. Something went terribly, terribly wrong when the “div” approach was adopted. It is not at all intuitive. Plus, there are no wysiwyg products that make development as easy as it was with Front Page using tables.

    I am eager to try this tutorial after frustrations with other books and tutorials, but I am not optimistic.
  32. Eric Irvine

    1812 days ago

    Actually I would say that it is pretty intuitive, you just have to get in there and try things out! I went from tables to css in alittle over a month. I just basically took some old table layouts and converted them, learning along the way. And in my humble opinion, wysiwyg editors are crap, period. Especially so when you don’t know what your doing in the first place because of their awful code output, just my 2 cents, notepad all the way. C’mon if you can code with java, php, and pearl then css shouldn’t present that much of a challenge… just because it doesn’t work 100% as intended : P

    check out my Bloglines feeds under resources and design blogs. You might find some good tutorials and places to learn stuff, there’s only 80 or so feeds there :)
  33. If Else

    1811 days ago

    In the same way that relational DB development (i.e. SQL) requires a different mentality from ‘traditional’ procedural (and I use this loosely to encompass OOP such as Java), so it is when it comes to developing with CSS and developing with tables.

    This is why guides such as the one that John has written here are so valuable to the community.
  34. demetris

    1756 days ago

    the page are real art man.

    BRAVO!!!
  35. dg

    1753 days ago

    regarding the “i pulled support for IE” note: unfortunately, that’s where I too had to make the choice to quit reading. while we all love the idea of a non-IE browser utopia, the fact of the matter is that I have to develop for a corporate environment whose security structure is based in Active Directory, and whose transparent auth into the intranet domain is only most assured via IE. so, im stuck. the pages wont look as good, but then again, i wont have to suffer back-end dismantlement…
  36. John

    1751 days ago

    A late thanks sure beats no thanks.
    Great write up and nice code.
  37. nea

    1733 days ago

    This is da best ever i seen.
  38. Todd

    1727 days ago

    Thanks for the great article. I’m new to web programming, and I wanted to find out about CSS before I went too far. With your tips, I should be able to save a ton of time on site maintenance.
  39. Mauricio Samy Silva

    1720 days ago

    Hello John,
    I request your permission to write a free tutorial (in brazilian portuguese language) adapted from this great article.
    Best regards
  40. Robert Diaz

    1710 days ago

    I’ve come across many “3-col layout” tutorials. This one is by far the easiest to understand and the least CSS code-heavy. Good stuff. Play on playa.

    Simplicity. Simplicity. Simplicity.
  41. MySchizoBuddy

    1705 days ago

    How do u make so if any of the Nav bars r missing, the main content expands. so the user can have either a single column, 2 or 3 column. Lets say we don’t have a left nav, the main content should start from left most border and expand till it hits the right nav bar. and if left exist but the right doesn’t then content expnds till the right edge of the fixed width layout.

    Any pointers :)