Flexible Responsive CSS Grids

Published 21:47 on 28 March, 2012

There are many ways to build CSS column grids; all of which have their pros and cons. In fact CSS3 has begun to implement a built-in model for columns which will be most useful in the future. However, until all the browsers our users surf the interwebs with are capable of this, we’ll have to rely on the good old CSS2 tricks to do it.

For a good while I used defined width floats for my grids. This means you have to calculate the width of each column and fix it (either with pixels or something more flexible like ems or percentages). That method is flawed due to rounding errors and general problems with flow when resizing. A better method is to use a mix of floats and negative margins for positioning. When I need to create a CSS column grid, I use this method.

However, when I was recently asked to share my method—which was outlined to me by a good friend and CSS guru—I had to remind myself how to do it. These are the perils of becoming a manager and developing less. In the interests of remembering next time (and also sharing the knowledge), I’ve decided to document the method in this article.

A word on frameworks

Just a quick word really. There are frameworks out there that will do your grids for you. I know they exist but I do not use them. Often they result in bloated mark-up and esoteric element identifiers that create unmaintainable code. Your mileage, of course, may vary.

I’m capable of creating a grid with the minimum possible code required. Hence, for production purposes, that’s what I do. In a prototyping situation, when I need something quickly and painlessly, I may choose to favour a framework; but it hasn’t happened yet.

If you choose to use a framework to set-up your grid, this article probably isn’t for you.

Source order is important

It’s good to make sure your main content is first in your source order. It’s helpful for accessibility, and it’s (a bit) helpful for SEO. This is something that isn’t always easy to enforce when using traditional grid techniques. The technique I use is actually built around this concept.

Building the mark-up

The simplest possible mark-up we would want for a three column layout would be something like this:

<div>
    Main content
</div>
<div>
    Secondary content
</div>
<div>
    Navigation
</div>

To make it a little easier to target, and to make it a bit more readable, we can add some element identifiers:

<div class="main container">
    Main content
</div>
<div class="related container">
    Secondary content
</div>
<div class="navigation container">
    Navigation
</div>

This gives us three containers for our columns. If we were to use the simplest possible method of floating each column left and fixing their widths, we’d have ourselves a column grid. However, that grid would not respond reliably cross-browser and could pick up wrapping errors. It also requires exact knowledge of the required width of ALL columns. Depending on how we’d like our grid to respond to change, this may be suboptimal.

Floats

A floated element is shifted to either the left or right of its containing box and surrounding content then flows around it. Floating multiple boxes stacks them up either left or right, which is useful behaviour when attempting to simulate columns. However, if there is not enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.

Floats are taken out of the normal flow of the document. This means the positioning model is changed somewhat and we can use that to our advantage.

The trick

Applying a negative margin to a floated element allows us to control how it makes use of empty space around it. We can make use of this if we add an extra wrapper to our main content:

<div class="container">
    <div class="main">
        Main content
    </div>
</div>
<div class="related container">
    Secondary content
</div>
<div class="navigation container">
    Navigation
</div>

To make two satellite floats react correctly we need to make sure that our newly added container is also taken out of the normal flow of the document with a float. However, we don’t want surrounding content to flow around it so we should fix its width to 100%.

.container {
    float: left;
    width: 100%;
}

Next we want to put some space around our main content using standard margins:

.main {
    margin-left: 150px;
    margin-right: 200px;
}

Now let’s fix the width of those satellite columns:

.navigation {
    width: 150px;
}
.related {
    width: 200px;
}

This will result in our three containers floating alongside each other. However, because the first container is set to a width of 100%, the two satellites drop down beneath it.

We want the satellites to take up that nice clear space we’ve created with the normal margins on our main content within the first container. To do that, we shift them left across the first container using negative margins:

.navigation {
    width: 150px;
    margin-left: -100%;
}
.related {
    width: 200px;
    margin-left: -200px;
}

Here we’ve shifted the navigation container 100% across the width of the container of our floats (in this case, the body of our page). This puts it flush to the left, filling the space to the left of our first floated container.

We then shift the related container only 200px to the left, matching its width and therefore leaving it flush to the right of the first floated container.

This leaves us with a perfect three-column grid. What’s more, since we’re only fixed the width of our satellites and have left the main content in normal flow, it will respond to the width of its container, as will the position of the satellite floats.

Demo and source

I’ve taken the above and scrubbed it up a bit, to create a nice flexible responsive CSS grid demo page. Further to that, I’ve also stuck the code up on GitHub in a “flexible CSS grid” repo. Feel free to do with it as you wish.