2 Column CSS Layout

Though a lot of web developers are beginning to migrate to css in their sites I still see many developers struggling when using css to layout their sites. CSS styling is usually pretty easy to grasp, but it can take some time to get comfortable with using css positioning techniques to layout a site. All too often I see the same developers moving back to tables so I thought I would present a few simple layouts, beginning here with a 2 column css layout.

I’ve created a 2 column layout using css, keeping things as simple as I could. Instead of just presenting the layout I want to work through the code here and explain some of the common pitfalls that I’ve come across and show how this simple layout overcomes those obstacles.

There are plenty examples of css layouts online though most of the 2 and 3 column ones that I’ve seen only include the columns themselves. I’ve included both a header and a footer in my layout. While the header is easy to include the footer tends to trip people up so I wanted to add it here and offer some explanation about how to integrate it into the layout.

The image below is a typical layout for many websites. A header at the top, a menu to the left, a main content area to the right, and a footer at the bottom. You might see something like this centered on the page. You can click the image to open it in a new window or tab and view the source code while reading about it here.


Click the image above to open the layout in a new window

Let’s look at the basic html structure for the page and then see how css is used to layout the various elements. The html structure is quite simple.

<div id="page">
 <div id="header">Header</div>
 <div id="menu">Menu</div>
 <div id="content">Content</div>
 <div id="footer">Footer</div>
</div>

We have each of the four sections of the page represented by a single div and then all four are enclosed in a ‘page’ div. The ‘page’ div is included so we can center everything in the browser window. There’s not much exciting going on here and it’s rather basic. All you need to notice is that each element is represented by a single div and that the order they sit in the structure is pretty straightforward as well. Nothing in the structure itself indicates that the layout will be in 2 columns.

Of course the interesting part is the css which surprisingly is rather simple as well. In fact only one of the elements even needs css positioning applied to achieve the layout. Can you guess which one? Let’s look at the css for each of the elements one at a time in the order they appear in the html structure.

Page Div

The page div is included in the layout to center everything. It’s represented by the thin purple border around everything on the page. It’s not really necessary in the 2 column layout, but I’ve included it since many sites are centered in the browser and some people have trouble doing this with css.

div#page {
  border:1px solid purple;
  width:755px;
  margin:0 auto;
  padding:5px;
  text-align:left;
}
div {
  text-align:center;
}

The border, padding, and text-align are purely for formatting. The text-align on the generic div is to center the single word of text within each div (header, menu, content, footer). I needed to add the text-align:left to the page div or it tries to center the 4 divs inside it in Internet Explorer. While you might use any or all of these properties they have nothing to do with the centering of the overall page.

To center the page you need a width which I’ve specified here in px, but could be any valid width such as % or em. You also need a margin which is set to auto for the left and right margin. If you’re not familiar with css shortcuts the way I’ve specified margin here is the same as saying 0 for the top and bottom margins and auto for the left and right margins. That’s all it takes to center your page. Just wrap your entire page in a div, give it a width and set the left and right margin to auto. You also need to use a proper doctype for your html in order for this to work in Internet Explorer.

Header Div

The header div is even more unremarkable than the page div. All I’ve included is a border so you can see it and a height and width. In real pages I’d typically set the width to be 100%, but used px here for no real good reason.

div#header {
  border:2px solid red;
  width:750px;
  height:30px;
}

The header appears just where you might expect. Since it’s the first element inside our page div it displays right at the top of the page. As it does that automatically there’s no reason why we need to add any kind of css positioning to it. In fact not adding any positioning to it will make it easier to set the menu and content divs.

Menu Div

Again the menu div has a border and I’ve also applied a width and height to it. Nothing really new here. There’s also a margin which I’ve used just to give the div a little space from the border of the page div. The menu div is our one positioned element. Did you guess it was the menu div? Let’s look at the code to see how it’s positioned.

div#menu {
  border:2px solid green;
  width:200px;
  float:left;
  margin:10px 0 10px 5px;
  height:350px;
}

The menu div is positioned by floating it to the left. When something is floated in css it’s taken out of the normal document flow. As far as the other elements on the page are concerned it’s been removed from the same document space they occupy and other elements can thus occupy the same document space. I think this is one of the harder aspects of css positioning to grasp. In this layout unless we tell it otherwise the next element on the page (in our case the content div) will want to sit in the same exact place the menu div sits. It can since as far as the content div is concerned the menu div has been removed from the document so to speak. With floated elements it’s not quite that simple, but for the purposes of this layout we can stay with this simple concept of document flow.

Content Div

As with the other divs the content div has a border applied to it as well as a width. Again nothing special about either of these. I do want to discuss each of the three other css properties so let’s take a look at the code

div#content {
  border:2px solid blue;
  width:500px;
  margin:10px 0 10px 235px;
  min-height:500px;
  _height:500px
}

The get the content div to display where we want we don’t need to use css positioning. Here all that’s been done is to give it a left margin to place it to the right of the menu. Remember that without doing anything the content div will be located all the way to the left in the same space the menu div occupies. Again that’s because the menu div is no longer in the normal document flow due to the float. You can test this by copying the source code and removing the 235px from the left margin and see where the contnet div moves.

CSS positioning could have been used either by floating the content div or using absolute or relative positioning. I think this is the common first thought when creating a css layout. The instinct is to use positioning on everything. But there’s a reason why I didn’t use it. I want to keep the content div in the normal document flow. Keeping it in the normal document flow helps to keep the footer div always sitting right below it. Had positioning been used and the content div been removed from the document flow as well as the menu then the footer would want to occupy the space just below the header.

The menu div usually has a fixed amount of information in it and generally won’t change height from page to page. The content div however will often change height based on the how much content it contains. Most of the time there will be enough content so that it has a height greater than the menu. When it does the footer will sit at the bottom of the page and everything will look great. But if the content isn’t enough to give the div a greater height than the menu the footer will come up to sit below the content (now shorter than the menu) and will end up overlapping the bottom of the menu.

Because of this I’ve added a min-height to the content div. The min-height assures us that the content will always have a greater height than the menu div. If the content needs the div to grow longer it will automatically, but by adding min-height we can be sure it will never be too short. Unfortunately Internet Explorer doesn’t handle the min-height property and so I’ve used _height as a sort of min height hack. IE actually interprets _height as height and all other browsers ignore it. Fortunately Internet Explorer will still expand past this height when the content needs it to so _height does act the same way as min-height. Incidentally you can use an underscore in front of any css property and know that only IE will interpret it. I’ll use this sometimes when I need IE to have a different value for a property than other browsers. Just make sure to use the underscore version of the property after the valid property.

Footer Div

Because we’ve accounted for the footer div in the way we set up the content div nothing special needs to be done to it. It looks exactly like our header div in fact. Just the by now familiar border, width, and height.

div#footer {
  border:2px solid red;
  width:750px;
  height:30px;
}

i think footers cause a lot of problems for people when they begin to layout a page with css instead of tables. I see lots of questions about how to position it and others asking why it’s not sitting where expected. Here by not using css positioning on the content we’ve solved the problem and let the footer naturally sit at the bottom of the page where we want.

This simple structure has been built as a 2 column css layout. No tables allowed (unless you have data for your content that should make use of a table). Even though our 2 column layout uses css to position the various elements we only needed to use css positioning on one element in our layout. Keep that in mind as you develop your own layouts. Just because you’re not using tables doesn’t mean you need to use css positioning on everything. By limiting the use of it here we’ve simplified things and eliminated some problems that often arise.

By no means is this the only possible way to develop a 2 column css layout. Below are some links to other css layout resources that may also help in the development of your sites. Feel free though to use my 2 column css layout as a basic structure in your own sites.

Resources

CSS layout techniques
Layout Boxes

« »

Download a free sample from my book, Design Fundamentals.

47 comments

  1. Glad I could help ella. When I looked around at other css templates I didn’t see much in the way of explanation so I tried to make this one simple and understandable. Keep in mind that this isn’t the only way to code a 2 column css layout. It’s just one way and the way I chose when writing this post.

    Glad it was helpful.

  2. THANK YOU VERY MUCH..

    CSS never sounded soo understandable in any tutorial to me. Thanks alot for this post. You saved me from quite a trouble. Keep writing pal.

    regards…

  3. Hello,
    I am a newbie to CSS. I like the simplicity of your 2 column CSS based layout and I haven’t found any other website that explains so clearly. However, I am having trouble rendering even the basic 2 column in IE7. The “Menu” column always floats away. But it is NOT a problem in FF3. Any suggestions? Thanks. You can view the file at:

    http://garnet.acns.fsu.edu/~tsomasun/van.html

    The code is copied directly from your tutorial.

    • Thanks for the compliment Thay.

      The one thing I notice is in your css file you’ve repeated the html structure at the top

      Try removing this code from your css file:

      <div id=”page”>
      <div id=”header”>Header</div>
      <div id=”menu”>Menu</div>
      <div id=”content”>Content</div>
      <div id=”footer”>Footer</div>
      </div>

      When I look at the page I created here in IE7 it is working. The html above in the css file is the one major difference I’m noticing and I think it may be causing the problems you’re seeing. I think it’s canceling the css for div#page below it somehow. Without that wrapper div the menu floats to the left edge of the body.

      Somehow in your example the menu div isn’t seeing the page div as it’s container. It sees the body as its container and floats to the left edge of the body.

      I hope that makes sense.

      I do think the issue is in the html code in the css file. I think if you remove it everything will work.

      If it doesn’t let me know and I’ll be happy to take another look.

      • Steven,
        Thanks a lot. I didn’t realize that I left the code hanging in there (.css). I was trying to debug the .html code rather than look at the .css file, showing that I have lot to learn and think slightly differently.

        Thanks. Keep up the good work.

        • Glad to help Thay. Sometimes you need that second set of eyes. It’s easy to get caught trying to debug something when the problem is really someplace you aren’t looking.

          I can’t even begin to count how many times I’ve done the same thing.

  4. Thanks for this tutorial. I’ve been looking for a 2 column layout with header and footer and yours is the first one I’ve found that falls together nicely and with a minimum of code. Your explanation makes a lot more sense than others I’ve tried also.

    I was going to ask you how to get the menu to expand to 100% height but I just figured it out by copying the height data for the content to the menu and it worked.

    Thanks much!!

    • Glad to help Lori. I tried to keep this post to a minimum amount of code to make the basic concepts easy to understand.

      I actually layout a site a little differently than I talk about here. I now float both columns to the left and then use clear: both on the footer to hold it below the columns. But the method here still works.

      One of these days I’ll update this post or write a new one on how I code things now.

  5. Great design, thank you! Your sample works well, but With some header modifications I kept getting double the left margin showing up for the content in IE. So, there is something picky about the design in IE which I can’t quite put my finger on.

    • Thanks. I’m glad you like the post and the sample is working well for you.

      IE has a bug (As though that’s a surprise) when an element is floated in one direction and also has a margin applied in that same direction, the margin gets doubled.

      So if you have an element with

      {float: left; margin-left: 20px}

      the element will end up getting 40px of left margin instead of 20px.

      The solution is fairly simple you can add

      display: inline

      to the element and the margin should go back to what it’s supposed to be.

      position: relative also works I think.

      Adding either shouldn’t mess up anything else, but if you want the extra css to only take effect in IE you can always use conditional comments

  6. This tutorial has worked the best out of all that I’ve tried. There’s only one thing; although the content is aligned next to the sidebar how I want it to be, it doesn’t show up until after it. Any suggestions? I don’t believe I altered any main components of the code.

    If you need to see what I’m talking about, my url is virgosplash.com

    Thanks for your time.

    • Sarah I took a look at your site. I’m not exactly sure why, since I only looked quickly, but when I removed most of your left margin and then reduced the width of the content div a little it slid back up where you want it.

      This worked for me, though you may still need to adjust it to suit your tastes. If you want more margin-left you’ll have to reduce the content width by the same amount.

      margin: 10px 0px 10px 10px;
      width: 600px;

      If you want I can take a longer look when I have the time to see if I can figure out why the extra margin was causing the problem.

      I actually use slightly different code to layout a site now. Sometime in the not too distant future I hope to write a new post with the new technique. I think it’s a little simpler.

      • That’s odd, but it works.

        Thanks for your time! I’ve been messing around with it all day and resorted to google and wasn’t able to come up with anything. I appreciate your help.

        • Glad I could help. I’m sure there’s a reason why taking away the margin did the trick, but at least it’s working now.

          Check back here in the coming weeks and I should have an updated method for what you in this post.

  7. Hi Steven,

    I’m currently learning CSS. The 2nd edition of “CSS the missing manual” arrived today so hopefully this’ll help a lot! The 1st edition had really good reviews on Amazon.

    I’ve been going through the material you presented above. Hopefully you (or someone else) can clear up my confusion though…

    Under the section Menu Div, you say “when something is floated it is taken out of the normal flow and as far as the other elements on the page are concerned it’s been removed.” Also: “unless we tell it otherwise the next element on the page (in our case the content div) will want to sit in the same exact place the menu div sits”.

    This is not what I observe though. If the stylesheet is trimmed to remove stuff relating to the content div and the footer div, then the content still sits to the right of the menu and not on it. That’s my main confusion.

    As an aside, I’ve been trying to learn from w3c spec about floats and found this paragraph: “Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist. However, line boxes created next to the float are shortened to make room for the margin box of the float. If a shortened line box is too small to contain any further content, then it is shifted downward until either it fits or there are no more floats present. Any content in the current line before a floated box is reflowed in the first available line on the other side of the float. In other words, if inline boxes are placed on the line before a left float is encountered that fits in the remaining line box space, the left float is placed on that line, aligned with the top of the line box, and then the inline boxes already on the line are moved accordingly to the right of the float (the right being the other side of the left float) and vice versa for rtl and right floats.”

    When it talks about line boxes created next to the float, I don’t really know what that means. I know what a line box is, but when it says “next to”, does that mean as a sibling in the document, of as a child somewhere of a sibling in the document? In the case you present, the content is a div (therefore a block box) which contains a line box with “Content”. Is this line box “next to” the floated menu using the terminology of the w3c site?

    I feel like I’ve just dumped my worries off to an agony aunt, apologies. Any clarifications you might be able to provide will be gratefully received!!

    Regards,

    PUK

    • First don’t feel bad if you find floats confusing. They’re probably one of the most confusing things about css. Once you “get” them you’ll find it opens up a lot of possibilities.

      I probably won’t be able to answer all your questions in a comment, so maybe I’ll have to put this on the list for an upcoming post. In fact I just made a note to start that post.

      My second statement about the next element wanting to sit in the same spot, probably isn’t so accurate. What happens depends some on whether the next element is an inline or block level element and it also depends on how much space there happens to be around the floated element.

      A float element floats within it’s containing element. So if you have a paragraph that starts with an image (which you float left) followed by the usual text, your image will float to the left and the text will wrap around it.

      If that same floated image isn’t inside the paragraph then the text will appear below the image (I think?).

      Where it gets confusing is if you have a div and then float all the different elements inside that div. As far as the div is concerned there’s nothing inside it so if you give it a border on all 4 sides you’ll at most see a single line.

      I’ll work on a post for next week to see if I can clear some things up for you. Seems like a good topic to cover.

  8. Hey! Thanks for the instructions. I’m only seeing problems in IE6 and IE7. The content div is to the right of the menu div, but it’s way too low! I must be doing something wrong.

  9. Hi,

    i want to ask how can i make a border that will be round menu and content, becouse ive got div which separates them from other staff but it doesnt work, thanks for help, i cant find it anywhere

    • Hi Paolo. I’m sorry I didn’t see your comment until now. It depends how your site is set up, but you might try wrapping both the menu and the content in a container div and applying the border to the container div.

      If that doesn’t work then you could try adding 3 sides of borders around each of the menu and content and don’t add any border to where the two connect. Assuming there’s no space between menu and content that should give the effect of a single border around both.

  10. This is where I don’t get CSS. When I try to edit this so I have both left and right columns the same width and unlimited height, it just becomes a mess. I simply need two colums with a border around the whole thing.

    • If you post a link or send me the code I can take a quick look at what the problem might be. The width part should be easy. You just have to make sure all the widths (including left and right padding) add up.

      For example if your overall page is 800px you could make each column 400px. When you start adding margins around the columns or padding within you’ll likely need to adjust the column widths.

      Unlimited height is a little different. If you don’t specify a value for the height then the columns will expand as the content inside them grows. Having them always be equal height is tricky though. There are a variety of solutions to the problem, but it’s one thing css hasn’t always done well.

  11. I had a problem getting this layout to work in IE7 and IE8 while I was playing around with the layout to see how it worked and to learn more about css layout. I’d used topstyle free to edit the HTML file and it added a “edited with topstyle” comment as the first line in front of the Doctype declaration. This apparently triggers a bug in IE7 and IE8 which switches the browser into quirks mode which caused the content DIV to not overlap the menu DIV even though I’d removed the content DIV margin. At first I simply got confused and thought I’d misunderstood the basic concept of document flow and positioning etc but after a bit of removing of apparantly extraneous lines of HTML and trying and then a bit of internet searching found info on the pre doctype declaration comment quirks mode bug which restored my understanding of your layout principles.

    Your article is one of the clearest explanations of css positioning I’ve come across, many thanks.

    • Thanks Paul. Interesting how the comment through everything off. In general you never need to any those comments about which program was used to edit a file. Still it’s interesting how it sent IE into quirks mode.

      On the positive side having to spend all that time trying to figure out what was wrong, while frustrating, made you a better coder. Similar things happened to me when I was first learning this stuff. I’d be chasing down some error. I’d learn so much along the way, often new things not connected to the problem I was trying to solve.

      By the way if you’re interested in css positioning, I wrote another post dedicated to the subject.

      How Well Do You Understand CSS Positioning?

      Hopefully you find it helpful.

  12. Hello Steven,

    Just wanted to chime in to say that you have a very natural way of explaining things. The float sitting below the content now makes perfect sense. Previously, it used to be a trial and error method for me.

    Thank you for sharing your knowledge.

  13. Hello, thanks for the good articles, very useful.

    Esteven, I have a doubt:

    Is it possible to give a color to the spaces there are out of the body (right and left side)?

    • Those spaces should still be part of the body so you could add a background-color to the body. Otherwise you could add it to the wrapper div, which in this case I called page. So add a background-color to either body, #page, or both.

  14. Thanks Steven, I forgot to mention I had not used a div to wrap the content in the boby. so I had used the body tag to set the page width

    Anyway after making my first question to you, I kept trying and added a background to the html tag directly and worked

    I have been practicing in making a site that looks well in 800×600 resolution but found that looks not good in higher resolutions, so I guess will have to apply some responsive features

    Regards

    • Oh. Yep that does make a difference, but you figured it out that you have to add the background-color in that case to the html element.

      What you’re finding with the 800×600 layout is exactly right too. A big reason for going with responsive design is that what works best at one resolution probably won’t work great at another.

      If you haven’t seen it yet, here’s a post I wrote about 2 and 3 column layouts that will work better for a responsive site. The layouts will be flexible so they can grow and contract with the browser. You’d still want to do a little more for a real responsive design, but the post I just linked to will help with the flexible layout part.

  15. Thanks Steve for your post on layouts. You have really taken out the mystique about CSS layouts. However, I am still having a problem with making the content section positioned correctly. I tried using the code exactly as you recommended. Please what am I missing out:

    See my code below:

    2 Column CSS Layout

    div{
    text-align:center;
    }
    div#page {
    width:755px;
    margin:0px auto;
    padding:5px;
    text-align:left;
    border:2px solid green;
    }

    div#header {
    border:2px solid purple;
    width:750px;
    height:30px;
    }

    div#menu {
    border:2px solid blue;
    width:200px;
    margin:10px 0 10px 5px;
    float:left;
    height:350px;
    }

    div#content {
    border:1px solid purple;
    margin:10px 0 10px 350px;
    width:500px;
    min-height:500px;
    _height:500px;
    }

    div#footer {
    border:2px solid red;
    width:750px;
    height:30px;
    }

    Header
    Menu
    Content
    Footer

  16. Hello. Your site is very good and useful to me as an aid in my job. I am still in the learning phase and wanted to know if you had anything published that would help me understand horizontal nested navigation w/ 2 or more levels.

    Thank you!
    Ava

    • Thanks Ava. I haven’t published anything on nested navigation that i can remember. Whenever I need a drop down though, I’ve usually turned to this menu from HTMLDog

      The drop downs are vertical in their code, but I think they mention how to convert it to the drop downs are horizontal.

  17. Hey you!
    Would you have believed it, if 9 years ago, I told you that your site would be used a decade from now for learning all over the world?
    Because it is.
    I am struggling with the basics of CSS and it seems that everyone just puts in code without explaining how everything interacts with the site, or what happens when we use A or B.
    You do a great job at explaining and it helps to know what I am doing.
    Thank you so much, and I hope that I will find more useful information the more I keep reading you 🙂
    -E

    • Thanks Emilie. I know what you mean about sites with code and no explanation. That bothered me when I was first learning so I decided to put in the effort to learn what I could and do my best to explain why I was using the code I was showing.

      I’m glad it helps.

      However, you should know that I don’t usually build layouts using the methods I described in this post. You might want to look at the posts on this page. You can probably skip the first two, but check the other 3 and then click to the second page for 2 more.

      Those aren’t exactly how I would develop a layout now, but they’re much close to what I would do.

      Thanks again.

Leave a Reply

Your email address will not be published. Required fields are marked *