in Tutorials

Building a Responsive Two Column Layout

UPDATE #3: A new article has been added that addresses the layout issue with this solution. Please read about the new version of the codebase if you want to avoid the document flow issues found in this tutorial.

UPDATE #2: Added navigation/menu section to the demos. The GitHub repo and CodePen example has been updated.

UPDATE: Based on numerous comments about how to include a footer in the layout, I have added a footer to all examples with accompanying styles. Thank you everyone for your feedback! The GitHub repo and CodePen example have been updated as well.

tl;dr version

  • Demo
  • CodePen
  • Github Repo
  • Use min-width media queries to progressively enhance the layout of the design.
  • Use “box-sizing: border-box” to calculate borders as part of the total width of an element.
  • Use Scott Jehl’s Respond.js polyfill for min/max-width CSS3 Media Queries (for IE 6-8, and more).
  • All wireframes were created using Balsamiq Mockups. I highly recommend this tool for making quick wireframes.

Introduction

This tutorial will explain how to create a two column layout with one fixed column and one fluid column. The example is basic, but it can be expanded to have multiple columns, even fluid nested columns. We will start with a mobile first view that consists of the columns stacked on top of each other. We will later add media queries to make the columns sit side by side as screen size allows.

I created this tutorial because there are many examples on how to use a grid framework for responsive layouts, but not enough examples on how to create a custom layout that doesn’t need a full blown grid framework. Those frameworks are wonderful and very educational, but typically I don’t need an entire grid framework. I just need a simple flexible layout. I don’t need the overhead of styles that I won’t use and I have no use for a 12 column grid system.

Let’s imagine a layout that has a fixed right column of 300 pixels wide (or 18.75ems, if you are using 16 pixels as your baseline) and a left column that will be fluid. The left column will be for main content. The right column will be used for sidebar content. A place for ads, links, or other ancillary content.

The HTML is fairly simple with a container div to hold the left and right column.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Responsive Two Column Layout</title>
  </head>

  <body>

    <div class="columnsContainer">

      <div class="leftColumn">
        <h2>Left Column (fluid)</h2>
      </div>

      <div class="rightColumn">
        <h2>Right Column</h2>
      </div>

    </div>

  </body>
</html>

Base CSS

For the default CSS (read: mobile), let’s add some rules for the column container such as a .5em margin and set the position to relative. This is important as it will come into play later when we make the left and right column align side by side. For the right and left column we’ll add some basic rules such as a 1 pixel border for demo purposes and padding to make everything look nice. I could have combined some of the rules for .rightColumn and .leftColumn for efficiency, but I have separated them out for clarity in this example. Here are the default CSS rules:

*, *:before, *:after {
  -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}

body { margin: 0; }

.columnsContainer { position: relative; margin: .5em; }

.leftColumn {  border: 1px solid  #ccc; padding: 1.25em; margin-bottom: .5em; }

.rightColumn { border: 1px solid  #ccc; padding: 1.25em; }

Also note we are adding a global rule for the box-sizing. This is set to “border-box”. This rule is a hidden gem that Paul Irish blogged about a few years ago. It changed my life. For real. If you have ever struggled with the extra padding that CSS borders typically generate on an element, then this will change your world as well. Check out his article, “ * { Box-sizing: Border-box } FTW” for more information on this awesome CSS bit.

Now our content will be easy to read in any browser. It should look something like the following screenshot.

Wireframe of a two column layout in a mobile view

Progressive Enhancement with Media Queries

Now we want to make the columns align side by side when the screen size allows. A good breakpoint for this design is 47.5em (760 pixels). Since we are using a mobile first and progressive enhancement approach, we are going to use a min-width media query to handle the breakpoint. And as a result, we only need to add a few lines of CSS to achieve the desired layout. Here are those rules:

@media screen and (min-width: 47.5em ) {
  .leftColumn { margin-right: 19.5em; }

  .rightColumn { position: absolute; top: 0; right: 0; width: 18.75em; }
}

Now we will have a layout that looks something like the following screenshot:

Wireframe of a two column layout in a typical desktop view

The Details

Let’s walk through what is going on here. The media query states that when the screen size is greater than 47.5ems, apply the rules inside the @media block.

The .leftColumn will add a right margin of 19.5ems to allow for proper padding between the left and right column. We could have written a right margin of 18.5ems, but that would have made the columns butt up against each other. I like pretend that the left column has personal space issues and prefers an ample amount of padding between himself and others. So we give him a little extra padding to make him feel safe inside of his purple circle. This will remain intact regardless of how big or small the screen size gets, there will always be a right margin of 19.5em for screen sizes above 47.5ems. And the width of the left column will stay fluid.

The .rightColumn will now have a fixed width of 18.75ems (300 pixels). We also set the position of this div to absolute with a top and right of 0. The real magic going on here is the relationship between .columnsContainer and .rightColumn. Since the container div is set to relative positioning, the absolute positioning of the right column is now relative to the container div. This will guarantee that the .rightColumn will not stray outside of .columnsContainer. Without this rule, the .rightColumn would be absolute positioned to the body element. This would result in the .rightColumn div aligning with the top-left of the browser window. We don’t want that. This set of rules will ensure that the right column will always be flush with the top-right edge of the container div.

If you were to look at this website in IE 8 and below, you would notice that the media queries do not load and the layout takes on the default styles of the columns stacked below one another. This is because IE 8 and below do not support media queries. You can get around this with a handy polyfill created by the amazing Scott Jehl called Respond.js. It adds support for min/max width CSS3 Media Queries.

Conclusion

This is one of many approaches to responsive design layouts. I hope it benefits someone out there. It has been working quite well for me. Feel free to comment on your preferred method of making responsive columns.

Here is a link to the demo page and the github repository if you want to quickly grab the files. I also created a CodePen if you want to tinker with the layout in real time.

All wireframes were created using Balsamiq Mockups. I highly recommend this tool for making quick wireframes.

Leave a Reply

39 Comments

  1. It took me a day to fix this issue for multiple breakpoints. Your tutorial came as a blessing for me. Thanks a ton!!

  2. I don’t usually comment on these things, but wanted to THANK YOU! Your tutorial and starter templates were the breakthrough I was looking for. I tried using Dreamweaver’s new Responsive/Fluid design interface and it is glitchy and I just wanted an old school, build it yourself template. Yours is the only one working for me AND it helped me understand how the whole fluid thing works. You saved me a lot of frustration!!! I hope the Universe rewards you in some way for sharing this knowledge with others. 🙂

  3. Dear Ryan, Thank you for the great help with this tutorial. I have a question. How can I make the fixed column a little bit wider? When I increase the width from 18.73em, the fluid column goes out of alignment. (Sorry for my precarious language here) For me, the fixed column should look about the same width of the fluid, in desktop screen. You know, like the classic two column divided by two (50% each) I hope I make sense. Thanks a bunch!

    • Rodrigo,

      You would have to adjust reduce the margin-right properties for the leftColumn class and increase the width property for the rightColumn class. You could change them both to 50%. However, please use the updated version of this codebase as this solution uses absolute positioning and isn’t the best way to approach this type of layout. The new version is covered here: http://www.johnstonianera.com/building-responsive-layouts-redux/

      Hope this helps, happy coding!

  4. hi i’m using Two Column Layout in my project . i’m using leftColumn and rightColumn class for desktop and mobile . but in mobile when page will open rightColumn come top and leftColumn will come bottom. but it is not happening . can any one tell me how can i solve this problem.

  5. Hi, first of all thanks for this tutorial, ive been looking for something like this for ages.

    It all works perfectly but im having a bit of an issue (because im fussy) i was wondering if on the mobile version it was possible to have the right column sit above the left column? Im not too great with css and cant find the bit which corresponds with the position of the right hand column.

    • Shonnie,

      I did some googling, and it looks like you can change the display properties of the right column and left column to get your desired outcome. Try adding display: table-header-group; to the right column and then add display: table-footer-group; to the left column style. This should flip the order of the columns.

      For more details check out this article. Looks very handy: http://tanalin.com/en/articles/css-block-order/

      Hope that helps,
      -Ryan

  6. I have use your layout with my current project… The one fix left and fluid right… How can I force an element or div inside the fluid right to occupy the entire width of the fluid right column…? In your example if I put less word in the container adjust its width…

    • Pardz,

      Are you having problems filling the entire width of the right column because the right column has padding of 1.25em? Assuming this is the issue you are talking about; there a couple approaches you could try.

      1. Remove the padding of 1.25em on the rightColumn style. Then all elements would be flush with the left and right sides of the column. You would then need to add padding for every element inside the right column that you didn’t want flush.

      2. Add a right and left margin of -1.25em to the element or div that you want to occupy the entire width of the right column. For example:
      margin: auto -1.25em;. This would retain the top and bottom margin, and only effect the left and right margin.

      Also, I would recommend using the updated codebase for this project that can be found here: https://github.com/Johnstonian/simple-responsive-layouts

      The article detailing the changes can be found here as well: http://www.johnstonianera.com/building-responsive-layouts-redux/

      I hope this helps. Let me know if you have any more questions.

      Happy coding!
      -Ryan

  7. Hello, I’ve incorporated your design into an existing wep page and it works very well. I’ve placed my own text into the right box but now have an issue when I resize my browser. The content in the right box is cut off about mid-way.

    It’s a media queries issue, I’m sure, but I don’t know where to begin!

    I don’t want to impose, but can I send you a link to the page in question?

    Thanks in advance.

  8. Superb tutorial and greatly appreciate the clear instructions and all the links! Everything works great except, like a couple of others, I cant get the footer to stay at the bottom.

    I’ve got a 2 column left fluid and if the text in the right column is longer that the left then the footer moves up under the left column. Using your CodeFlex I doubled the amount of text in your right column & the footer moves up. So I followed your instructions on another post “If you want a \”sticky\” footer, please take a look at Galen Gidman\’s solution, it\’s pretty solid: http://galengidman.com/2014/03/25/responsive-flex… ” but cannot seem to get this to work!

    If you have any guidance on this I’d really appreciate it! Thanks in advance.

    • Kate,

      There is a document flow issue with the current solution I’ve detailed in this article. By absolute positioning the right column, this effectively takes that div out of the document flow. By that, I mean that the rest of the HTML document is unaware of the height and any content in that section. Which is why the footer will overlap with the right column if the right column is longer than the left column. You could do some hackery to add more height to the left column, but it will probably cause you problems in the long run.

      I’m working on a revised version of this codebase to alleviate this document flow issue. Until then, please check out the many excellent CSS grid systems. Most notably http://www.responsivegridsystem.com/ and http://foundation.zurb.com/grid.html

      Thanks,
      – Ryan

      • Hi Ryan,

        Thanks for getting back to me! Because this footer isn’t my actual site footer (just the bottom section of the page) I can live with it for now. I’ve bookmarked your page and will check back later for a revised version.

        I find it remarkable that you publish code (that works) for other to utilize for free, write detailed instructions AND provide support! Really appreciate it Ryan.

        Thanks again.

  9. Hi Ryan – I find the 2 column set-up works beautifully for all of one thing…I cannot get menu inserted that does not go into the left column! Could you tell me where to insert the code for this to work…I really appreciate an answer and thanks for this great tutorial…Joan

    Responsive Two Column Layout (Left Column Fluid)

    Left Column (fluid)

    • @Joan,

      You can add a new div above the “columnsContainer” div to house the menu. I’ve updated the code examples to include a menu system at the top of the layout based on your comment. You can see an example here: http://codepen.io/johnstonian/pen/guhid

      The three column layout example has a menu on the left, if that is more what you are looking to create: http://johnstonianera.com/demos/simpleResponsiveLayouts/three-columns.html

      I’m glad you found the tutorial useful. Please let me know if you have any more questions. Happy coding!

      – Ryan

      • Hi Ryan – thank you so much for the update of the code, that was so thoughtful of you. I also like the 3 column one. I do have one more question though, the font keeps showing up as Times New roman and I can’t seem to change it. I have tried putting it everywhere in the body and separate as as p {
        font: Helvetica Neue”, Helvetica, Arial, sans-serif;
        color: #666;
        } Do you have any suggestions? Once again you are really great to help us newbies like you do…Regards, Joan

        • Joan,

          Fonts can be tricky. If you, or the user loading the page, does not have Helvetica installed then the css will default to your third font declaration, Arial. Helvetica is installed on Mac computers, but not on Windows machines by default.

          If you use Chrome, I recommend installing the excellent WhatFont Extension. It gives you the capability to click on any text on a website and display which font is being rendered. It can be found here: http://chengyinliu.com/whatfont.html

          Also, if you want to ensure every user that loads your page gets the same font experience, then I’d recommend using an embedded font service like TypeKit, https://typekit.com/, or Google Fonts, https://www.google.com/fonts. Font Squirrel, http://www.fontsquirrel.com/, is also nice for embedding fonts.

          Lastly, be sure you are declaring your css fonts correctly like the following:


          font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;

  10. Wow, an old-school tutorial! I missed these so much. I appreciate the effort you put into explaining things step-by-step.

    I think I got used to SO where they assume you know a lot of things (and are slightly, uhm, snarky if you don’t). Or the “199 Ways To Do Something” post where they just link to different tutorials that confuse you even further.

    Your way is more helpful for someone who wants to learn. Thank you! 🙂

  11. This is very helpful except as someone new to this, I find without navigation and a footer, there is a lot that I can’t figure out so easily. I can’t seem to get the footer I created to stay at the bottom. Also a follow up tutoiral on creating a responsive navigation menu would be awesome. Any ideas or suggestions about the footer?