Percentage-based CSS column layouts

20th December 2013 | More information

Laying out a page using percentage-based columns seems to be pretty easy. However, in responsive layouts, you’ll quickly run into problems if you don’t take legibility into account. The most obvious case is when the columns are predominantly text-based, where a suitable gutter between the columns is essential for the sake of legibility.

(If you want to skip the theory and just get the code, you can check it out in my GitHub helpers repository.)

I have recently needed to produce layouts for content containers into which two, three or four columns need to be positioned. The mathematics for these proportions are simple: 50%, 33.333333333333% and 25% respectively.

The rule for a three column layout needs to be defined to a deep level because of rounding. Because the most modern browsers handle pixel rounding differently, you have to be careful of values being rounded up or down. The more specific you are, the better. If your measurements exceed 100% by even 0.001%, your layout will break. That’s why the thirds-value is so specific: to twelve decimal places.

The problem with these simple figures is that they don’t take the space between the margins – known as gutters – into account. Columns places without gutters make a great big mess when filled with text, as there’s no way of knowing where one piece of text ends and where the one next to it begins.

In fixed-width layouts, you’d just add a 20px gutter between the columns and make the columns correspondingly narrower. In responsive layouts, you need to define the values as percentage measurements.

My typographic testing indicates that a value of 2.66666666666667% is a good basis. In a full-width layout – say 1200px – this gutter width works out to around 30px. That’s a good gutter to place between text blocks, so that the words have sufficient whitespace between them. If you use an advanced implementation of these examples, where content is split into two columns on narrow screens and four columns at wider sizes, the gutter width will remain equally logical.

In the following variations, we’ll use the same value for gutters in all three layouts, and we want the columns to reach to the edge of their container.

I prefer to add gutters between the elements as a margin, so that it’s easy to know where the individual content boundaries lie. The gutter percentages then relate to the overall width of the layout in all browsers, not to the containing column.

By using this formula, each column width in a four-column layout needs to be set to 23%. A simple number to remember. By dividing the remaining space left over after defining your columns (4 x 23% = 92%, remainder 8%), you get the target gutter width of 2.66666666666667%.

Four column percentage-based layout

Switching to the three-column layout, the individual column widths become slightly less easier to remember. Without any gutters, the columns are already complicated, at 33.333333333333% each. Take the gutters into account and they’re a little less easy to remember: two gutters at 2.66666666666667% each total 5.33333333333334%, leaving you 94.66666666666666% for your three columns. That works out to 31.55555555555555% each.

Three-columns percentage-based layout

The two column layout is fairly simple to work out: take 2.66666666666667% from the total width and you have 97.33333333333333% remaining for your columns. Halve that and you get 48.66666666666667% per column… but watch out! Add those figures back together and you get 100.00000000000001%, which will break your layout!

That’s down to the rounding effect at such a detailed level, so adjust your figures. Retain the gutter width of 2.66666666666667% for the sake of consistency, but set your column widths to 48.666666666666665% each: this will total exactly 100%.

Two-column percentage-based layout

Hopefully, that mass of slightly overwhelming but relatively easy mathematics makes sense. Even if you’re not quite sure of the principles after a first time reading my explanation, you can see a real-world example of code implementation in my GitHub helpers repository.