3 Column CSS Layout: Fixed Width And Centered

Last week I shared the code I use to start a 2 column fixed width layout. Today I want to expand that code and share how I’d build a 3 column layout that’s also of fixed width and centered on the page.

Many of the concepts will be the same as in the previous post so I’ll skip some of the details here. If you need more explanation than this post has I’ll refer you back to the 2 column layout post.

There will be some new concepts when we try to move the columns around for which I’ll offer a more detailed explanation.

For those who prefer to skip the explanation here’s a demo of what we’ll be building and you can view the source for the code.

3 column layout: primary sidebar main content secondary sidebar

The HTML

As with the 2 column layout, the html for a 3 column layout is rather simple. In fact the only real difference is one additional div for our third column.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div id="container">
        <div id="header">
        <p>Header</p>
    </div>
    
    <div id="primary">
        <p>Primary Sidebar</p>
    </div>
    
    <div id="content">
        <p>Main content</p>
    </div>
    
    <div id="secondary">
        <p>Secondary Sidebar</p>
    </div>
    
    <div id="footer">
        <p>Footer</p>
    </div>
</div>

Instead of using sidebar-1 and sidebar-2 I’m calling the sidebars primary and secondary. You’re free to call them whatever works best for you.

One point to make about the html is the order of the divs. If you remember last week we moved the columns simply by changing the direction of floated divs. We’ll do the same here, but that alone won’t allow us to reorder the columns in all possible ways.

I’ll get to the details in a bit, but with 3 columns there are 6 potential ways to order those columns. We can achieve 4 of those 6 ways just by changing the direction of the floats. For the last 2 we’ll need to use some relative and absolute positioning.

CSS tab inside Coda editor by Panic

The CSS

Once again the css is rather simple and should be familiar if you read the previous post. And just as with the 2 column demo I’ve stripped away css that’s only there to make the demo more presentable. Here’s the css we need for this layout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#container {
    width: 960px;
    margin: 0 auto;
}

#primary {
    float: left;
    width: 240px;
}

#content {
    float: left;
    width: 480px;
}

#secondary {
    float: left;
    width: 240px;
}

#footer {
    clear: both;
}

There really isn’t anything new here when compared to the 2 column layout. We’ve used our container div to center everything on the page and floated our columns to the left. Lastly we cleared the footer.

If you need explanation about what’s going on please see that explanation in the 2 column layout post.

While I’ve floated all 3 divs to the left, you could also float the rightmost column to the right. In this case that would our #secondary div.

I typically float all columns in the same direction, though I think it’s more common to float the rightmost div to the right. Like I mentioned last week, I’m unaware of either being better or worse.

Floating everything in one direction made it easier for me to understand when I first started working with floats and now it’s become habit.

Columns - Temple of a Thousand Warriors

Rearranging the Columns

The first way to rearrange columns is to reorder their divs in the html. When first developing a site you’ll likely structure your html how you want the columns to display on the page.

There will be times though when you want to move the columns around after the site is live or because you want to the columns to have different orders on different pages without having to change the html.

Fortunately we can rearrange the columns through css alone and doing so will hopefully make for a good learning experience.

I mentioned above there were 6 possible ways we could order the 3 columns.

  • primary, content, secondary
  • secondary, content, primary
  • content, secondary, primary
  • primary, secondary, content
  • secondary, primary, content
  • content, primary, secondary

Not the most logical order to list them I admit, but there’s a reason why I’ve listed them this way.

The first order above (primary, content, secondary) we’ve already coded. The next 3 on the list we can get to by changing float directions. For the last two we’ll need to mix in some positioning.

3 column layout: secondary sidebar, main content, primary sidebar

Secondary, Content, Primary

When we float all 3 columns in the same direction they will always display in the same order they appear in the html. That will be true regardless of whether we float all 3 to the left (as we’ve done above) or to the right.

If we float all 3 divs to the right we’ll get the reverse order of how they appear in the html, which is all we need to achieve this column order.

The easiest way then to have all 3 columns display in the same sequential order as they appear in the html is to float all 3 in the same direction either left or right.

3 column layout:  primary sidebar, secondary sidebar, main content

Primary, Secondary, Content

To get the next two layouts on the list we’ll change the direction of a single float so it’s in the opposite direction of the other two.

When we float any 2 of the 3 columns in one direction and float the third in the opposite direction, the one floated opposite will sit at the outermost edge in the direction it’s floated.

If we want to move our main content div to the right we’ll float our main content to the right and keep primary and secondary floated to the left.

As you might expect the two sidebars display to the left of the content in the order they appear in the html. In our case the primary column will be leftmost and the secondary column will appear to it’s right.

3 column layout: main content, secondary sidebar, primary sidebar

Content, Secondary, Primary

Similarly if we want our primary column to be the rightmost column we float it to the right and float the other 2 columns to the left.

Again if 2 columns are floated in one direction and the third is floated opposite the opposite will display at the far end of the same direction it’s floated and the other 2 columns will display in the order seen in the html.

3 column layout:  secondary sidebar, primary sidebar, main content

Secondary, Primary, Content

Unfortunately we need to do more than change float directions to get the last 2 orders.

Let’s think for a moment about how we might go about setting up this column order. Since we want the main content column to be rightmost let’s start by floating it to the right.

One of our 3 columns is now where want. We’re left needing to swap the order of the primary and secondary columns.

Your first instinct might be to float the primary column to the right, but that will place it to the right of the main content. What we need to do is add some positioning. Fortunately we don’t need to add a lot.

I won’t be able to offer a full explanation for how positioning works here so I’ll direct you to my post on understanding css positioning if you need a more detailed explanation for why the following works.

First we’ll add relative positioning to our container div

1
#container {position: relative}

This won’t affect our #container div at all, but it will allow us to position columns relative to the container div. If we skip this we’ll be positioning columns relative to the body of our html.

Next we’ll remove the float and add absolute positioning to the primary sidebar.

1
#primary {position: absolute}

If we stop here something strange happens. Our primary column hasn’t moved, but our secondary column seems to have vanished.

By default our primary column will have a value of 0 for it’s left property, which keeps it right where it was. However by changing from a float to position the primary column no longer holds the secondary column to its right.

Our secondary column is now hiding behind our primary column. Understanding why is a matter of understanding the css stack and the z-index property.

We need to move the primary column further to the right, which will also reveal the secondary column. We do so by increasing the value of left to be equal to the width of the secondary column

1
#primary {left: 240px}

And now all 3 columns are displaying exactly where we want.

3 column layout: main content, primary sidebar, secondary sidebar

Content, Primary, Secondary

To get our last layout we need to reverse the order of the columns we just set up above.

Here we want the content on the left and the secondary column on the right so let’s switch the direction of the floats for both.

Not bad. We’re almost there. In fact the only problem at this point is the primary div isn’t far enough to the right. We just need to alter it’s left value to match the width of the content.

1
#primary {left: 480px}

and we’re done.

We used the same basic concept in both of the above orders.

The column we wanted to be furthest left we float left. The column we wanted to be furthest to the right we float right. For the column we want in between we used absolute positioning and gave it a left value equal to the width of the leftmost column.

We also made sure to add relative positioning to the container div.

Note: Like our 2 column layout this won’t create columns of equal height as it appears in the demo. The columns have equal height because I set their heights to the same value. Creating equal height columns is something for another time, though I promise to write a post about how before too long if you’re interested.

A section of code from Kate code editor

Summary

Setting up the css for a 3 column layout isn’t really any harder than setting up the css for a 2 column layout. The same principle of floating all the columns in the same direction applies.

If you’ve understood this and the last post you should now be able to create 4 and 5 column layouts as well.

What’s a little trickier is rearranging the columns. We changed the float direction of columns to achieve several column layouts and used positioning to get to a couple more.

If you’ve been following along you now have several different methods for setting up multi-column css layouts regardless of how many columns and regardless of the order those columns appear in your html.

I’d encourage you to play around. Change floats and position different columns. Try adding a 4th column and see how you can reorganize all of them.

In this and the last post I’ve given you some instructions for moving blocks around on a web page. Spend some time moving those blocks around. The more you experiment on your own, the greater you’ll understand how and why this all works.

Next week I’ll continue with fully fluid layouts. The principles will be very much the same as they are here with one key difference.

Download a free sample from my book, Design Fundamentals.

52 comments

    • I mentioned it in the 2 column post that either is fine. I’ve always preferred to use a container div. I prefer thinking of the body as filling up the browser window and I think using the container gives a little more control over things.

      However that’s just my preference. I know others prefer using the body tag as the container. The important thing is that something needs to contain the entire layout, whether you use the body tag or create a new container is up to you.

  1. I would really be interested in seeing how you create equal height columns. That’s always been a challenge for me. I’d appreciate any tips you can provide or better yet, a new post on how to do it for others to benefit as well.

    Great work!

    Thanks,

    Mario Hernandez

    • I’ll definitely write a post about equal height columns. I’ve already started making notes for it. There are a few methods for equal height columns, though I have one or two favorites.

  2. I think this is a great tutorial for beginners or for designers transitioning from table based layouts to CSS based layouts. It’s not even hard to learn as well. It took me 10 minutes to figure out how to organize content this way and I think I’m really glad that I’m using CSS layouts not.

  3. Thanks Butch. This and the other posts I’ll write in this series have beginners in mind.

    I think when a lot of people first approach css to layout a site it gets confusing. They gravitate toward position instead of float and I think there’s a tendency to try to use more css than necessary I wanted to show little css you really need to get the basic layout down and hopefully explain why it works.

  4. As a beginner, I appreciate your clearly-written, organized and well-thought out explanations and examples. Thanks!

  5. Thanks for the article!

    But: I still cannot solve my 3-col-problem. I want to make 3 cols. First and third col should be liquid, the middle one should be of fixed width. Altogether it should be 100% of the screen width.

    Can anyone help? I would appreciate that very much.

    • I would need to see your code to be able to offer a specific solution. Feel free to post a link if your page is online or send me an email with the code if it isn’t.

      The basic issue though is that since you want the center column to be fixed the % of the 2 outer columns will change as the browser resizes. Odds are what you want to do is wrap all 3 columns in a div that’s set to 100%.

      Then set the width on the center column and locate it within the wrapping div by setting a % margin. If you want the center column centered in the overall layout give it a left and right margin of auto. If you don’t want it centered give it a left margin of whatever % width you want the left column to have.

  6. If your having collapsing issues, don’t forget to use

    #container {
    overflow: hidden;
    }

    This will wrap the container element correctly around the columns (rather than collapsing the container)

  7. Thanks for this info. I’ve been having fits with a three column layout with your html/css I was able to figure some things out more completely and hopefully get my page to render properly in IE and Chrome.

    Couple of points. The page won’t center in IE unless you add a text-align: center for the body css. Also if anyone adds padding to the columns, the Chrome browser will not like it, you need to create a new div within the div, e.g. and do your padding there.

    Thanks Again.

    • Glad I could help.

      Is it an older version of IE that isn’t centering the page? The margin auto technique should work in IE. You do need to specify a width of some kind on the wrapper and you also need to use a proper doctype. Without the doctype I think IE goes into quirks mode and then the centering won’t happen.

      Otherwise it should. I’ve never had a problem with it.

  8. Hi Steven,

    I’m attempting to rebuild a very old html table layout using your “formula” and it’s working great so far. Only one problem. I needed to change the columns like your 5th or 6th option so I am using your instructions. Once I have added the relative/absolute positioning, however, the column I changed no longer affects the height of the container. That is, when I put the primary column in the middle (which I’m doing for SEO purposes, so my content is first in the html rather than left navigation)the footer doesn’t move down when the primary column is longer than the other two. I’m sure this is an easy fix, but I just can’t get it right. Thoughts? Thanks for the great tutorial!

    • Hi Jolene. I think what’s happening is that the footer is clearing the floats, but unfortunately the middle column, which is the longest, isn’t being floated so it isn’t being cleared.

      The basic problem is coming up with another way to get to the footer to clear the main column.

      Try wrapping a container div around all 3 columns and then setting overflow: hidden on that container div. You might also have to float the container right or left. I don’t think it will matter. Then the footer should clear the new container div and that div should be forced open to the height of the middle column.

      I think that will work, though don’t hold me to it. If it doesn’t let me know and I’ll dig a little deeper into my code to find another solution.

  9. Hey Steve. Thanks for your help with this. I’m picking up HTML/CSS using dummies books. They reccomend:

    #all [
    background-color: grey;
    width: 480;
    margin -left: auto;
    margin-right: auto;
    ]

    It works and seems more efficient, however it might restrict HTML options in the columns. Any thoughts.

    • Hi Danny. It looks like that code is doing the same thing as the id=”container” div I wrap around everything.

      The #all code is basically doing the same thing. It sets a width on the element and then gives it a left and right margin of auto.

      I used the shortcut margin: 0 auto, which is essentially the same thing. I set 0 for the top and bottom margins and auto for the left and right.

      Assuming #all is some container div, then it’s really doing the same thing I am.

  10. Thanks for your response! Still can’t get it to work, though. Here’s the code I’m using:

    Content

    Left Sidebar

    Right Sidebar

    footer

    and the css:

    #wrapper {
    width: 960px;
    margin: 0 auto;
    background-color: #FFFFFF;
    }
    body {
    background-color: #003399;
    }
    #left_sidebar {
    width: 200px;
    float: left;
    }
    #content {
    width: 558px;
    position: absolute;
    left: 200px;
    }

    #right_sidebar {
    float: right;
    width: 200px;
    }
    #container {
    background-color: #FFFFFF;
    float: left;
    position: relative;
    width: 960px;
    overflow: hidden;
    }

    #footer {
    clear: both;
    float: left;
    height: 25px;
    width: 960px;
    }

    This is making me crazy! Thanks for your help!

    • Jolene is the page online somewhere?

      Your html didn’t come through in the comment. If the page isn’t online you can email me all the code and I’ll take a look.

      I’m not seeing anything in your css that should throw things off. I’ll probably need to see all the code so if you can’t point me to the page if it’s online or email it all to me it’ll help.

  11. Your work here really helped me with a problem iv been stuck on, would you mind helping me though, how do i align images in the center of the div’s? You can check out the site, iv just been using sample images, but i cant seem to get it to work.

    Thanks
    Daniel

    • Thanks Daniel. Glad I could help. I’ve actually written a couple of posts ago all about centering.

      For horizontal centering and for vertical centering

      Horizontal centering is easier. You give the element you want to center a width and then you set it’s left and right margin to auto.

      element {
      width:80%;
      margin: 0 auto
      }

      That should center it within its containing element.

      Vertical centering is a little harder to describe here in a comment, but the post I linked to offers 6 different methods.

  12. First of all, thank you for this tutorial – I used it step by step and it works like charm in IE. But Firefox (11.0) does not center the content and shows the secondary sidebar underneath the first.

    Could you give me a hint what to do about this?

    Any help will be appreciated!

    Thanks,
    -Brigitte

    • I’m glad you found the tutorial helpful Brigitte.

      This should work in Firefox, though I think I know why it isn’t. It’s probably because of the way the box model works. My guess is you adding some right and/or left padding or border to one or more columns. That has the effect of increasing the width of those columns and they now probably total a greater width than the width set on the container.

      You don’t see it in IE because IE got the box model wrong based on the spec (though they actually do it how most developers prefer)

      The fix is to reduce the width of any column where you added left/right padding or border, by an amount equal to the amount of padding/border added.

      Another fix if you don’t need to support IE7 or below is to set how the box model works in your css.

      * {box-sizing: border-box}

      Chris Coyier has a really good post about box-sizing on CSS Tricks with all the details.

      Hope that helps.

  13. Really interesting tutorial. I’m wondering though if there’s a way to have the div in the center have a constant width (or a max & min width) while the other two divs on both sides fill the rest of the screen with relative widths (50% minus half the width of the center div?). I’m still looking for a way to do this.

    • Thanks Jared.

      You could try setting the columns up as css tables.

      Wrap all three columns in a container and set the container to display: table and give it a width of 100%

      Then set each of the 3 columns to display: table-cell. Set the middle column to whatever width you want and the other 2 columns should split the difference by default.

      Something like this:

      <div class=”container”>
      <div class=”column”>Left</div>
      <div class=”column fixed”>Center</div>
      <div class=”column”>Right</div>
      </div>

      .container { display: table; width: 100%; }
      .column { display: table-cell; }
      .fixed {width: 500px; }

      Will that work?

  14. I have read many books and articles on the subject of creating columns in HTML5 and CSS3, however your article finally put in the brain housing group. Thanks.

    I do have some issues with CLEAR as how and where it’s used. Do you have an article on it?

    I have just begun to use JQM mobile and have some issues with over-writting it background to my own specified background. Seems their code overwrites anything I place in my CSS file or inline styles.

    Do you know anything about JQM mobile? Their forumt lacks assistance.

    GREAT JOB, I am now a viewer and user of your site

    • I’m glad I could help. This post leads into a few others. One on 2 and 3 column fully fluid layouts and one on creating flexible layouts for responsive sites.

      For clear, you probably want this article about floated elements. There’s a section about clearing elements, though it’ll make more sense if you read the part about floats leading up to it. It’ll explain when to use clear and why.

      Sorry, I’m not familiar with JQM Mobile. Are you adding their code after your own? That could explain why your css is getting overridden.

      • I placed the the testing where I’m trying to create a 3 column container within a page container. he footer is having a float issue as it is overlapping the columns. Plus the borders are not being displayed. Feel free to access’

        AS FAR AS jquery MOBILE – i talked to the support reps and the assure me that their cframework does not overide my CSS files. However I did a test, and the moment I link their CDN my background disappears.

        Oh well, so much for experts.

        • Yeah, I’m sure their first response is to say it’s not them. That seems typical in customer service.

          I got your email and see you did figure this all out. Glad to hear and glad I could help in some way.

  15. Hi There, great tutorial – as always. One thing particular to my site is that I have a Background image for my header which i’d like to be full width regardless of browser window size. Given your header and footer columns are fixed is there anyway to have 100% header+footer with background image along with fixed width 3 columns? I’m pulling my hair out on this one.

    Cheers

    Ian

    • Thanks Ian. First here’s a post similar to this one about 2 and 3 column fluid layouts. These layouts won’t have a fixed size and can stretch edge to edge.

      Getting an image to do that is more difficult. In your css file you can set:

      img {
      max-width:100%;
      height: auto
      }

      which will allow your image to grow and shrink as the layout does. However the image can only grow as large as the image is, meaning you’d have to create an image that’s as large as possible for the cases where the browser is very wide.

      Unfortunately that means people viewing the site on a phone still have to download this very large image.

      What you might try instead is to center a header image that has the same solid color at the left and right edges. Then set the background color of the header to be the same color. Using the code above your image will grow and shrink, but when the browser is wider than the image, the image will be centered and the background color fills the extra space.

  16. Thank you so much for the article and I’m with you! the less code laying around the more hair you can keep! I just knew there was a better way! Thank god for google and Steven!
    Have a great one!
    Thanks again for sharing!

  17. Hi

    Once again, thank you for your excellent tutorial. I am a beginner and will be coming forth with problems as I grow in learning CSS and HTML. I am very much interested in creating 3 column page, but they keep bunching together and appearing leanerly and not as 3 columns. Please what should I do?
    Davidson

  18. Hi Steven!
    I find your site extremely useful. It’s exactly what I needed and it is explained in a way that even I can understand :)
    However I have a little problem. I did the three columns layout and at the top of each column I have put h2 and then the text is in a p tag. The three sets of h2-s and p-s are in separate divs. The three divs are with width set and floated left. What is my problem? One of my headings takes two lines and ‘pushes’ the text from the p tag down one line. I want each p tag to start at the same line.
    Vertical align does not work here, I was thinking positioning the P-s and then setting top:…px., but somehow I feel maybe this is not the best thing to do. Also, I could insert a under the one line headings in the HTML , but that means it must be adjusted every time the content is changed. I was also thinking of display: table and display:row and so on, and then – vertical align, but I am sure the solution is much simpler, just somehow I miss it.
    Could you possibly advise me what would be best to do? I guess you are busy, so if you have no time – that’s fine. One learns best when tries to find solutions himself.

    Regards,
    Boryana

    • Thanks Boryana. Sorry I didn’t reply right away.

      Funny. I was going to suggest setting the height of the h2 as the best solution. I was going to suggest setting it to twice the line-height of the h2 so your headings could either fall on a single line or two lines.

      • Reading my question again I can not believe how complicated thing can I make out of something so simple… Anyway, I am still new in CSS, maybe that excuses me … for now.
        Thank you very much Steven, I will apply line-height as well.

        • Trust me, you’re not the first person to have done that and won’t be the last. I’ve taken many a simple thing and complicated it, especially when I was first getting started.

          And I still do it today. :)

  19. Hello and thank you in advance for any help you can give me. How can I get my header which is the title to center over the center column? Also how can I add links to other sites under my bio at the left? Also, I am putting on links to (private) pdf files for certain chapters of the book which will appear as updates under posts. How do I do this? Again thanks

  20. After looking at so many possible solutions, this is a sight for sore eyes. I needed a terse and to the point breakdown for a three column section that is several layers deep within a larger layout. This approach is completely sensible and works! Thank you.

    • Glad I could help Zac. Just so you know, I don’t develop fixed layouts anymore, though the layouts I use now are still pretty similar to the one here. They use relative measurements like % and em, instead of absolute measurements like px. Otherwise they’re still similar.

  21. I found your blog searching ideas and material to write a small guide for html and css. I really like 2 things on your blog, or maybe 3 :
    1.the way you explain things here
    2.the minimal design and “readability” of your content
    3.The subjects you choose to disqus.

    Thanks for the contribution, Keep on the good work !

Leave a Reply

Your email address will not be published.

css.php