Building a Responsive Two Column Layout

Now Reading
Building a Responsive Two Column Layout

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 Irishblogged 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.

mobileView

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:

desktopView

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 .rightColumnwould 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.

  • Vincenzo

    Hi,

    first of all thank you for this beautiful tutorial, but i’ve a question for you: on the “left fluid” design what happens if the right column is higher than left?

    There is a method to improve this grid? To place the elements after the grid (footer for example) correctly on the down side of the page and at the same time show correctly both columns?

    Thank you,

    Vincenzo from Italy