Flexible, responsive column system
Column layouts. Used almost everywhere, including on home pages, portfolios, product lists… Here’s a practical, tested and successfully used recipe for a good, flexible and responsive column system that will (hopefully) make your work easier.
What are we making?
Our column system should be lightweight, responsive and bulletproof. It will allow us to use any width of columns in any order we like. It also should be easy to use by non-technical people, who, for example build pages of WordPress shortcodes and have no idea how HTML and CSS works.
The question is: how?
Usually, the columns are block elements put one next to another. It’s quite obvious, but can be done several ways, for example by floating them to one side or by displaying them as inline-block elements, just like the pictures but inside text. Each of these approaches has its downsides.
Different approaches
Floating elements
The main fault of floated columns is clearly visible when there’s so many of them, that they don’t fit one row and start to show under the previous ones. When one the previous columns is long, the next ones will show beside it, instead of under it, which will make the layout quite a mess. The mess is even bigger if we give them some margins, and some of the columns should have no margin so their content could align with the text in the above parts of the page. Unless we use special elements to clear the floats, but they cause another problems:
- what is going to happen on smaller screens, on which we want to display less columns in a row?
- if we let users compose the page by themselves, we can never be sure they’ll remember to put the clearing <div> in the right place.
- the clearing <div> is an unnecessary element, from the document’s structure point of view
The inline-block approach
This approach is deprived of the floated columns’ downsides, yet it has a weakness: elements may have spaces between them if the person creating the markup wants to have a legible code or is building the page of shortcodes. Spaces between columns may break the layout by making – for example – two 50%-wide columns not fit the width of their container (some extra room is needed for the space or other white character). The way to avoid it is to set the container’s font size to 0. And this means we need a container for the columns only, so the rest of the page copy could be visible. One extra container vs many clearing elements? I think it’s a good trade-off.
Markup
And thus we came to the markup point: We need column elements inside a container. So our HTML would look like this:
<section class="columns"> <article class="column"></article> <article class="column"></article> <article class="column"></article> </section>
It doesn’t really matter if we use sections and articles, divs or whatever else – we’ll use classes for styling anyway.
Styling
Now, we’ll write the basic style for our columns. We want them to be flexible, always filling all the available space in the container. We also need some space between the blocks of text.
If you haven’t done it yet, put some text in the columns so you could see them work. Here’s a nice tool for dummy content generation.
.columns { font-size: 0; } .column { padding: 15px 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; font-size: 16px; }
I used padding and box-sizing: border-box
instead of margins so it would be easier to set column widths in percent and spaces between columns in pixels, no matter the screen size.
You probably noticed that now each of the columns extends to full possible width. Well, we want it responsive and mobile-first, don’t we? So this will be their default behaviour on small screens. What about the bigger ones? For the sake of this post, I decided to let them occupy all the width of the screen for devices narrower than 600px, half on screens from 601px to 900px and above it they’ll have widths set by their specific classes. Feel free to establish your own breakpoints and play with them as you wish.
So, the word ‘responsive’ implies media queries, so let’s add them. Put this code and the end of what you’ve just written:
@media (min-width: 601px) { .column { display: inline-block; width: 50%; padding: 15px; } }
Now, if you view the layout on a 601 pixel wide (or larger) screen, you should see two blocks of text next to each other and another one below them.
There’s still one small problem: if you place some text above (or below) the columns, you’ll see that the left edge of the text in columns isn’t aligned with the content above. Same about the right edge. The solution is quite simple: let the container have a negative margin on both sides, which will be equal to columns’ padding. Let’s modify our media query so it looks like this:
@media (min-width: 601px) { .columns { margin-left: -15px; margin-right: -15px; } .column { display: inline-block; width: 50%; padding: 15px; } }
Next, we’ll move to larger screens, on which we’ll implement various column widths.
Various column widths
Until now, all the columns look and behave the same. It’s time to create classes that will control the widths of the columns and will let you build the layout any way you want. To achieve this, we’ll add a new media query.
@media (min-width: 901px) { .full {width: 100%;} .half {width: 50%;} .one-third {width: 33%;} .one-fourth {width: 25%;} .two-thirds {width: 66%;} .three-fourths {width: 75%;} }
For this article, I decided to implement the following column widths: full width, half, one third, one fourth, two thirds and three fourths. Of course you can add your own sizes.
So for the most basic example, add the one-third class to columns in the markup you’ve written (remember about the content of the columns which I omit here for the sake of code clarity):
<section class="columns"> <article class="column one-third"></article> <article class="column one-third"></article> <article class="column one-third"></article> </section>
Now, your column system should work well on all screens and in any column configuration.
Summary
Here’s the complete CSS code for the column system:
.columns { font-size: 0; } .column { padding: 15px 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; -o-box-sizing: border-box; box-sizing: border-box; font-size: 16px; } @media (min-width: 601px) { .columns { margin-left: -15px; margin-right: -15px; } .column { display: inline-block; width: 50%; padding: 15px; } } @media (min-width: 901px) { .full {width: 100%;} .half {width: 50%;} .one-third {width: 33%;} .one-fourth {width: 25%;} .two-thirds {width: 66%;} .three-fourths {width: 75%;} }
And the basic HTML:
<section class="columns"> <article class="column one-third"></article> <article class="column one-third"></article> <article class="column one-third"></article> </section>
Now, let’s have some fun:
<section class="columns"> <article class="column one-third"></article> <article class="column one-third"></article> <article class="column one-third"></article> <article class="column two-thirds"></article> <article class="column one-third"></article> <article class="column one-fourth"></article> <article class="column one-fourth"></article> <article class="column one-fourth"></article> <article class="column one-fourth"></article> <article class="column one-fourth"></article> <article class="column three-fourths"></article> </section>
The column system built in this article is quite basic but still can be used for most column layouts. If you need to add more column widths, or change the appearance of specific columns, all you need is to add an appropriate class to the css and off you go!
Have any ideas for improvements? Feel free to share them in a comment!