Remembering: the CSS3 multi-column layout module

Because I will not shut up about CSS3, this time I’ve decided to show you a little bit of the multi-column layout module. This module allows you to layout the content of an element in multiple columns, like flowing text on a newspaper-type layout.

CSS Modules

Just to briefly make sure everybody understands what I mean by “modules”, the development of CSS3 has been divided in different Modules. For example, there is a Selectors Module, a Values and Units Module, a Backgrounds and Borders Module, etc.

Some of these Modules are at a more advanced stage of development and closer to being final than others. You can take a look at the Current Work table here.

Browser support

Let’s get this straight right away: only Safari and Firefox are currently supporting (some) of this module’s features, namely the properties column-count, column-width, column-gap and column-rule. Other browsers will render the content as if there were no columns at all.

There are more properties on the specs (and Safari supports a few more), but I’ll only mention these in this article, so we can all get a taste of what’s goin’ on.

Also, I’ve picked this particular module, because it’s one of the few that is actually in “Last Call” status, so it’s closer to being finished than others.

The markup

For this example I grabbed some text from the excellent Blind Text Generator and created a basic page with some divs and paragraphs.

Here’s an example of one of the divs:

<div id="text1">

	<p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</p>

	<p>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me? " he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls.</p>

	<p>A collection of textile samples lay spread out on the table - Samsa was a travelling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer.</p>

	<p>Gregor then turned to look out the window at the dull weather. Drops of rain could be heard hitting the pane, which made him feel quite sad. "How about if I sleep a little bit longer and forget all this nonsense", he thought, but that was something he was unable to do because he was used to sleeping on his right, and in his present state couldn't get into that position. However hard he threw himself onto his right, he always rolled back to where he was.</p>
	
</div>

The CSS

I’m just going to quickly show what each of the properties does. To use them, we’ll need to apply vendor-specific properties: for Safari the properties will be prefixed with -webkit- and for Firefox with -moz-. Annoying, but nothing we’re not used to, right?

Please follow the examples below on this page.

column-width

The CSS for our first div will be the following:

#text1 {	
	-webkit-column-width: 200px;
	-moz-column-width: 200px;
	column-width: 200px;
	}

This will create 200px wide columns until the width of the page is filled, with no gap between the columns.

Each column within the element is called a column box. A column box doesn’t have its own properties, like background, padding or margins (at least not for now, but that may change for future specs). Also, all columns within a row have the same width and the same height.

The column-width property is not definitive—it is actually the optimal size we want the columns to have, but that may vary if the container is wider or narrower than it would be required to fit those measures.

column-gap and column-rule

Now let’s add some space between the columns and a nice rule, shall we?

#text2 {	
	-webkit-column-width: 390px;	
	-webkit-column-gap: 20px;
	-webkit-column-rule: 1px solid #000000;
	-moz-column-width: 390px;
	-moz-column-gap: 20px;
	-moz-column-rule: 1px solid #000000;
	column-width: 390px;
	column-gap: 20px;
	column-rule: 1px solid #000000;
	}

In this example, we are defining a gap between each column of 20px and also adding a rule between each of them.

The column-rule property follows the syntax of the border property. Also, the column rules don’t take up any space—if they are wider than the column gap, they will (or should) overlap the content.

The column gaps and column rules are all the same within a row.

Ignore the colourful blocks in this example for now, I explain those bellow.

column-count

On our third example, we will specify how many columns we actually want the element to have:

#text3 {	
	-webkit-column-width: 200px;
	-webkit-column-count: 4;
	-webkit-column-gap: 20px;
	-moz-column-width: 200px;
	-moz-column-count: 4;
	-moz-column-gap: 20px;
	column-width: 200px;
	column-count: 4;
	column-gap: 20px;
	}

If both column-width and column-count are specified (like in this example), the column-count value will be regarded as the maximum number of columns. So if only 3 columns fit in the element, but you’ve set it to have 4, only 3 will be created.

If you don’t specify the width of the columns, the column-width will be calculated automatically according to how many columns you have specified.

Images, etc.

You can have elements, like images, along the text, and even float them or make them a percentage in width. That percentage will be calculated according to the width of the column box they are in.

To test this theory, I added 3 coloured divs to the second example (#test2), with some inline coding (oh, the horror!). The first, red, div is floated but it has a width of 140%; the second, green, div is not floated and it’s also 140% wide; and the third, yellow, div is floated, but has 100% width .

According to the W3C specification, this is what should happen:

Content in the normal flow that extends into column gaps (e.g., long words) is clipped in the middle of the column gap.

Floats that are wider than the column box intrude into neighboring columns.

Correct me if I’m wrong, but for what I see on these examples, Firefox is overflowing both 140% divs, even if the second one is not floated. Safari doesn’t do better: it’s overflowing neither of them.

More overflowing stuff

As a final example, I’m creating a div with a smaller width and a set height. I’m making the overflow visible, and see what happens…

#text4 {	
	height: 200px;
	width: 500px;
	overflow: visible;
	border: 2px solid red;
	-webkit-column-width: 200px;
	-webkit-column-gap: 20px;
	-moz-column-width: 200px;
	-moz-column-gap: 20px;
	column-width: 200px;
	column-gap: 20px;
	}

According to the specs, this is what should happen:

A multi-column element can have more columns than it has room for due to:

  • Constrained column height. […]

In continuous media, the columns that do not fit within the multicol element are added in the inline direction.

In human language, that means if the content is to be overflown, then it should be to the sides. In this case, Safari seems to be getting it right, while Firefox overflows the content vertically if the height is set via the max-height property, but correctly if via the normal height property. Take a look at the last block on the example page (with the red border).

Final words

And that’s it! I just wanted to remember you of this wonderful CSS3 feature that can make our lives a lot easier—and that degrades quite nicely for browsers that don’t support it.

I keep looking for examples of the multi-column layout in the wild, but I don’t think a lot of people are using it now. For what it’s worth, I’m using it on my personal site, yaili.com, and it’s also in use on the tweetCC website.

Do you know of any more websites using it?

This article has been translated into Belorussian by Amanda Lynn and into Portuguese by Artur Weber.