Introducing the CSS3 Multi-Column Module
Issue № 204

Introducing the CSS3 Multi-Column Module

A note from the editors: This article was experimental even in its day; make sure to research current CSS Columns specifications and browser support before deciding whether they are appropriate for your project.

While most computer screens are wider than tall, most websites are the exact opposite: longer than wide. In the economy of screen-estate, vertical space is expensive. If you were a piece of content, you would want to be above the fold, right? Horizontal space, on the other hand, is quite cheap; we often don’t even know what to do with it.

Article Continues Below

At the very common 1024×768 screen resolution, most fixed-layout websites don’t use all available space to the left and right of their content. Flexible layouts make a better use of horizontal space, but struggle to maintain usable line-lengths. Usability experts have told us that there are just so many words you should put on a line. Between 8 and 12 words seems to be the ideal line length. Print media, especially newspapers, don’t hesitate to use even shorter lines. Why? Because they can, by laying out text across several columns.

As a web designer, you can arrange a text so it flows into several well-balanced columns. Or at least you can try. But as you know, the web is not a medium that provides you absolute control over the final display of information. Your nicely crafted markup may turn out badly if your visitors, for instance, use a different font size or turn images off. Similarly, when you switch from static HTML pages to database-driven content, you lose whatever small ability you had to structure your text. Your markup, accordingly, needs to accommodate content of unknown size.

Of course, this problem is not new. Quite a few people have considered the problem, including the members of the W3C.

The CSS3 multi-column module#section1

The W3C multi-column module is a CSS level-three working draft, proposed by the W3C to extend the current CSS box model. The module’s intent is to allow content to flow into multiple columns inside an element. It offers new CSS properties that let the designers specify in how many columns an element should be rendered. The browser takes care of formatting the text so that the columns are balanced.

diagram contracting the single-column CSS box model with a CSS3 two-column layouts

The proposed new CSS properties are:

  • ‘column-count’, to determine the number of columns into which the content of the element will flow.
  • ‘column-width’, to describe the optimal width of each column.
  • ‘column-gap’, to set the padding between columns.
  • ‘column-rule’, to define a border between columns.

You can learn more about these, and some other new properties in the W3C working draft.

Multi-column implementations#section2

While the draft was published in 2001, it is still far from being a final recommendation, let alone implemented. Or is it?

Implementations in the browser#section3

The developers working on Gecko 1.8 (Mozilla & Co.) announced the first native implementation of the module in April this year, and the recent release of the Firefox 1.5 beta (based on Gecko 1.8) does indeed support parts of the CSS3 Multi-Column module.

We can only hope that more browser developers will follow.

Scripting implementations#section4

Other ingenious web developers have silently worked their way around the limitations of the CSS box model for quite some time. The International Herald Tribune, for instance, is using a JavaScript-driven multi-column layout for its news articles. Michael van Ouwerkerk, back in 2002, wrote a JavaScript that splits the content of an element and rearranges it into several columns. (Doubtless others have used similar approaches.)

One can certainly do wonderful things with JavaScript (and the document object model), and reworking markup to achieve a multi-column layout happens to be one of them.

With this in mind, let’s take a closer look at those new CSS3 properties from the W3C specification:

  • Column-count: That’s how many times a JavaScript needs to split content into left floating elements.
  • Column-width: That’s the width of each newly created element.
  • Column-gap: That’s a left (or right) padding for these elements.
  • Column-rule: That’s a left (or right) border.

Since such JavaScript would process the page after it is rendered, every factor that used to be a problem, font-size, images on/off, is already taken care of. Also, if JavaScript is not available, the layout would not be altered (in other words, it would degrade nicely).

An interim measure for experimentation#section5

Since it can be done, and since I wouldn’t be writing this article if I had nothing to show for it, here it is:  a (mostly) cross-browser JavaScript implementation of the CSS3 multi-column module. (View example.)

The implementation is an unobtrusive, stand-alone piece of code that acts as a JavaScript parser for this CSS3 extension. You don’t need any knowledge of JavaScript to use it, just upload the file to your site and link it to your page:

<script type="text/JavaScript" src="css3-multi-column.js"></script>

You can then start using the CSS3 properties in your stylesheets as you would do for any other CSS.

Cautions#section6

There are some limitations though that you need to understand. First, the browser-based CSS parser is designed to ignore properties that it does not support. To circumvent this, this implementation relies on a relatively simple parser written in JavaScript. This parser cannot handle complex constructions, like cascading rules spread across different selectors. Keep it simple. This following styles, for example, would be acceptable:

.article {
  column-count: 2;
  column-gap: 20px;
}

Secondly, the JavaScript cuts and moves content from one column to another. There are naturally a number of elements that cannot or should not be divided up: images for instance, but also tables, headings, etc. The algorithm tries to accommodate these content types, but can break or yield unexpected results in some circumstances. You are welcome to report any problem with the rendered layout and we’ll try to improve it as we go.

Browsers#section7

The script has been tested in IE6, Firefox 1.0.4, Netscape 7.1, Safari 1.2 and 2.0, and Opera 8 (though the Opera tests indicate a tendency to crash).

About the Author

Cédric Savarese

Cédric Savarese is a French expatriate located in the American Midwest. Besides overcoming the language barrier at the McDonalds drive-in, his toughest challenge is balancing his day job as a Web Developer, an expanding side-project (The Form Assembly), and a growing family.

53 Reader Comments

  1. Oh, my! Don’t use multicolumn layout on screen! Pleeeease!
    I like how it looks in print preview in Opera 8.5

  2. I have to say the concept here is very sound, particularly in formatting for print styles, however I feel that some testing will need to be put in to produce sound web implementation. I must admit, after reading Egor Kloos’ comment the prospect of up and down scrolling does not sound particularly appetising…

  3. Columnar layout is going to work much better with pages designed to scroll left to right rather than up and down.

    Up and down scrolling is just going to be tedious with columnar layout. But if pages show a series of columns no taller than the viewport, but the page scrolls left to right – this may turn out to be a very nice way of making sites that are easier to read and closer to physical media.

    Will require some development on the browser, HID front to make it workable though.

  4. … dictates that one should not specify the number of columns, but instead the number of words per line. Given that the motivation is to maximise readability by setting the number of words per line to a reasoable number and the fact that the viewport size is variable, it seesm to me that the best solution would involve specifying the number of words per line and make the layout engine determine how many columns are needed. Further, perhaps there should be a preference to say whether horizontal scrolling should be used instead of up-and-down scrolling (i.e. the engine lays out the text so that the preferred method of scrolling is required if necessary).

  5. Thanks for posting up this article, I can see this being useful not in implementing print styles as such but just doing the normal web tasks like having a list of related links to the right hand side. Yes that could be done with floats, but I’m thinking more along the lines of getting table based developers to cross over, where the mindset isn’t float left float right clear both, and that can only be a good thing.

  6. I see CSS3 columns as mainly useful within print stylesheets. On paper, there’s a benefit to fitting as many readable lines on as few sheets as possible. On screen, it doesn’t matter so much, as the scrollable browser is unlimited.

    As noted above, the text-at-viewport-height sideways scrolling approach where it wraps into as many columns as needed is the only real layout I can see succeeding onscreen. Mozilla’s implementation does support this, where you set the “height” of an element and the “column-count” is adjusted automatically, but sadly it’s not part of the W3 specs (IIRC, from PPK’s tests).

  7. bq. Let the up and down scrolling commence!

    Quite. Let’s have no more of that, thank you very much. It’s bad enough when someone is lazy and uploads a multi-column PDF for screen reading, but anyone *deliberately* *choose* such a layout deserves a good smack!

    Yes, I can see the benefits for multi-column layouts for short passages or lists, as in the other article this month, and in print stylesheets – but _please_ don’t encourage people to use multi-column “just because they can”. The example pages you’ve given in this article not only require vertical scrolling, but horizontal scrolling as well on my PC – a bad, bad, bad idea.

  8. I found this article quite interesting. I agree with “C R’s comment”:http://www.alistapart.com/comments/css3multicolumn?page=1#8 that if we intend to have 8 to 12 words on a line, then the ‘best’ way of saying how wide a column should be is by choosing the number of words desired. Of course, technically this would be very difficult: how wide is a word? How wide are 8 words? Should each column be the same size? I think this would prove difficult to standardize. Certainly when reading a newspaper you don’t want to see every column with a different width, based on the average number of words per line in that column! So I agree in principle, but in practice I think this would prove too unwieldy for those defining the standards, those writing the browsers and those designing websites to use succesfully.

    I decided to download the Firefox 1.5 beta in order to see how Gecko would display “Kevin’s example pages”:http://www.csscripting.com/css-multi-column/ . However after turning off JavaScript in Firefox the pages do not display columns at all but render as one big block of text. I tried the “Mozilla test page”:http://weblogs.mozillazine.org/roc/archives/2005/03/gecko_18_for_we.html cited in the article to see if that would render with columns and it did.

    Is this a mistake on my part, or is this a known “feature” of the script?

  9. I’m really glad to see a great artical addressing the problems of line length, scrolling, and space utilization; thanks for the excellent work, Cedric.

    In case anyone is interested, I have another “take on these same problems”:http://www.sumulshah.com/projects/codex/ .

    By the way, I noticed that when ordered lists get split across columns, the numbering gets reset to (1) in the second column in Safari (this is something I had to deal with in my approach too).

  10. Thanks for your comments so far. A quick response to those who brought up the scrolling issue. Yes scrolling should be avoided, but the CSS3 Multi-Column is just one more tool in the hand of the web designers. Let’s see how they use it before dismissing the technology altogether.

  11. Thanks for posting this interesting article and keep bringing more CSS3 goodies. Personally I didn’t know Firefox 1.5 beta supported CSS3 features already…

    Gonna start playing with it.

  12. The CSS3 module does allow you to specify a column width and leave column count as “auto”. In this case, the number of columns used will be determined by dividing the total element size by the column width. CSS doesn’t have a “number of words” unit, but “em” should be sufficient to provide a consistent width even with page scaling.

    If you’re trying to use Firefox 1.5 to play with column layouts, remember to use “-moz-” before all attributes. The policy over at Mozilla is to prepend attribute names with “-moz-” if they’re not yet a recommendation.

  13. I found it very useful to use this technique even on screen maybe it is not familiar yet but I think it will be great the only concern is to make sure that the columns height are not more than the browser height to avoid scrolling up & down more than one time.

    Thanks.

  14. This article appeared just as I’ve been working on trying to flow two columns for a print stylesheet. For a few moments I _thought_ that you were going to save me a lot of trouble with the JavaScript, but unfortunately it doesn’t work. The columns run the length of the whole article rather than just the length of a printed page. Drat. I suppose that finding the pagebreaks will be a real PITA, but since the browser can do it on the fly hopefully when the browsers implement this internally it will work.

    Thanks for the neato preview in any case.

  15. Real support for columns of content is one of the sexiest new things I can think of, but here’s a couple of thoughts –

    What about orphans (sentence fragments left over from paragraphs in previous columns) and hyphenated words? There should be properties for that as well… allow or disallow, tolerance levels, that sort of thing.

    Also – what if you don’t want the content to flow from one column to the next? And if anyone says, “That’s what tables / extra divs are for,” they get shot – both of those are substitutes for an actual solution.

  16. Honestly, I know it’s a cliche when someone comments in a manner of “I’ve been thinking of this myself…”. But, I have, because I am working on a new newspaper style portal design, and I want to transfer as much of the newspaper elements I can without affecting usability and design logic. I intended to use at least 2 columns of text in eac article display because I hate scrolling a long way down, in a single column layout, when the layout is fixed width. I don’t actually mind the scrolling, but the fact that I have to go back up again to reach navigation. (position: fixed; and such things are rare in this kind of sites)
    I originally intended to create some sort of a php function to divide my text to columns, but then the images would be a problem and so on. Thank You Cédric Savarese, for You have saved me a lot of time with this.

    Now, as for the up-down, left-right scrolling, I see a possible solution in seperating the content, not just into columns, but also verticaly. This way, we would have colums that have, at most, height around 70-80% of the viewport. This way, the scrolling would go only “downwards”. And you would not have to scroll often. Ofcourse, the problem of implementation still remains, but, it doesn’t seem imposible. Does it?

  17. Judgments on usefulness aside, I find it humorous that so many Web publishers are longing for a way to easily display content flowing across multiple columns, while at the same time that newspaper publishers are dreaming of pushing content on electronic paper in single, scrolling columns.

  18. Good work, Cédric. Thanks for bringing attention to the CSS3 multi-column implementations in today’s browsers!

    I would have enjoyed reading a summary of your script’s columnizing logic. From looking at the DOM of a test case it’s apparent that you’re dividing the text block into a series of divs, one per column. When a paragraph is split across columns, you’re inserting an empty span at the bottom of the first column to force that last line to justify. I’ll read your script to see what other rules you’re implementing.

    One point in your line-breaking logic to repair: in your “Test Case 2”:http://www.csscripting.com/css-multi-column/example2.php the last line of column 1 is broken before the comma:

    *Construction of the RMS* < *i*>*Titanic*
    , *funded by the American*…

    — perhaps the comma isn’t considered part of the preceding word because of the intervening HTML close-tag.

    Seeing how unsightly justified text looks in narrow columns brings to mind the various tools & rules that typographers use to eliminate rivers of whitespace when setting justified text, such as breaking hyphenated words across lines and implementing discretionary hyphens, things you might consider including in the scope of your columnizing script if it’s to be useful professionally. I look forward to seeing future renditions!

  19. Columns can be very usefull. Many pages of quality would be better with text in columns.
    But it will be a problem, if a column is higher than the viewport.

    Anyway, the article is rather good.

  20. Line 83 (*function loadCssCache*) of the file above:

    if(typeof xmlhttp.status == ‘undefined’ ||
       xmlhttp.status == 200 ||
       xmlhttp.status == 304
    )

    makes it impossible to use it offline via the file: protocol with gecko based browsers (tested with Firefox 1.0.7) as the returned xmlhttp.status is 0;

    Fix:
    if(typeof xmlhttp.status == ‘undefined’ ||
       !xmlhttp.status ||
       xmlhttp.status == 200 ||
       xmlhttp.status == 304
    )

  21. I used [nbsp][nbsp][nbsp][line break] to format code, as

     or  is not allowed: it renders well in the preview, obviously it doesn't on submit... don't know what to do - I uploaded my msg  "here":http://msg.byteshift.de/css3-multi-columns-by-js/
  22. The technique here is good and I thought the article was quite interesting. It’s experimental, but I can see it being very useful for print CSS specifically.

    I would only suggest we think very hard before using it on screen.

  23. I always thought columnar layout was appealing purely because it was difficult to achieve in a ‘proper’ way. Making it simple removes the appeal of using entirely for me. I certainly dislike it from a user’s perspective.

  24. After fidling for a couple of weeks with the idea of a columnar layout with a CMS like Textpattern, you come around and make something that works wonderfully. My only question is… Why couldn’t you do it earlier!

    Seriously though, thanks. I thought my head was going to explode.

  25. Marek, good catch. Thanks for the correction.

    Paul, the tools and information available in javascript to deal with line length and word separation are rather limited. This makes the column breaking logic a real headache. Basicaly, the scripts removes words after words until the column reach the desired height. The comma should be considered part of the word, but as you noticed the markup in between breaks the logic here… It’s probably something that can be dealt with in the script though.

  26. Hey Cedric,

    Nice work and thanks for the examples. I have one questions since I’m already using Dean Edwards latest IE7 scripts to enhance the native css support in IE. Would you be able to recommend an approach to providing your css3 enhancements as an additional module that could be loaded along with his css3 module? It looks like you base your functionality in part on his cssquery which IE7 also does. Seems like it should be possible to separate out the css3 enhancements so cssquery is common and this would be an extension to the IE7 project. That would be really handy. Any ideas would be appreciated. Again nice work.

    Mike

  27. I noticed that the script does the DOM wizardry by creating extra DIVs given random six letter combinations (like “ufsvmb”). I suppose making them a bit more meaningful would be helpful (besides, what about the unlikely event of a collision, eh?)

    Personally, I think that columns will open up the way to more paged forms of web presentation: splitting content up into several pages (something that personally irks me). The thing about doing that is that it makes things a bit easier when you want to bookmark, but I prefer my scrolling to your page turning any day.

  28. Thanks for the article Cédric, I’m finding it very useful in a current project. But I’ve run into a problem where your script seems to clash with at least one other script I’m using. I have a script in place that allows me to unobtrusively send external links to new windows. This script stops working with the multi-column script in place. If I rearrange the order, placing the external.js script last, the multi-column script stops working. I’m not script-informed (graphic designer with almost no coding abilities, sorry) so if there’s a way around the problem I’d be happy to here about it. (Otherwise I’ll have to skip one of the scripts, with a sigh and a tear, possibly.)

  29. Fred, send me a link to your page, I’ll check it out (c.savarese at 4213miles.com).
    Regarding the randomly generated id, they’re intended for internal use only, but it’s true that if you want to apply some css to one of the column only, a predictable id would be better.
    Mike, I use Dean Edwards’s CSSQuery, but I’m not familiar with the way IE7 works… we can talk about it further if you want. Email me.

    Thanks

  30. I am a cross-over from print design (magazines & junk-mail) – so hearing about this just gave me shivers! Imagine!!!!! A page that reads like a magazine–REALLY!

    One thing that does concern me is the scrolling. I have made sites that keep the scrolling to a minimum, and am going to be experimenting with CSS to see if I can do the same.

    Oh… THANK YOU for the Suckerfish Dropdown! Doing Velocity templates with drop menus was a real challenge until I found your tutorial! Now I have more time to experiment rather than debug!

    Aloha nui!
    LZ.designer

  31. I would really, *really* like both a column-height property, and not least a column-max-height property, last one making it possible to set the max-height of the columns (surprise!). If the content then overflows the columns, there should be created ‘more columns’ _vertically_.
    That would actually be _useful_ for something, quite contrary to what you achieve in Firefox 1.5 (RC1), when setting the height property on the ‘column-element’, giving you more columns horizontally (which is an understandable behaviour though, as it’s height, not column-height).

  32. I just thought it was ironic how the following line was placed into the article, yet the line after it had 14 words:

    Between 8 and 12 words seems to be the

    On, a more serious note, great insight, but will we really be able to use CSS3 for some time?

  33. I think this is a great way to make large amounts of text more readable (subject to the columns not being longer than the length of the viewport, of course). I’m definitely considering using it on a new website I’m just starting work on.

    One quirk I’ve noticed though is that the text in the first column has some whitespace above it, whereas the others do not which throws off the alignment of the text lines. This is readily visible in Test Case 5.

    Any way of sorting this out?

  34. My first column ends in the middle of bullet number 4 and is continued in the second column; it is renumbered as bullet 3. And again, the second column ends in the middle of bullet number 6, yet is reassigned bullet number 3 in the third column.

    Quite unexpected, indeed.

  35. I remember wishing that CSS could do something just like this. I think if the major browsers will impelement this in a reliable fashion, then it will increase the rate at which designers drop their nested tables in favor of semantic markup.

  36. It is my opinion that until all browsers support CSS3 web development will have to stick to calculating split points via scripts, either server side (e.g php) or client side (e.g. javascript solutions as shown).

    With the article script and indeed with the CSS3, what is really required is the abilty to set any element as no_break_within.

    Using the javascript supplied you can fool the javascript with

    • text


    to keep the text together. Unfortunately the side effect is that the last column tends to be the longest (at a guess the split point is set to the beginning of one of the elements).

    What is really required is if classname=”nobreak” or somesuch the split point becomes the end of the element.

    Another niggle which is required to be truly successful is orphan and widow controls although I fully realise the complexity this could cause.

    Thanks again for a useful article.

  37. First, 8 to 12 words per line is NOT the “ideal” or even magical number. It actually depends on a few variables – the entire length of the column, the point size of the type, etc. There is a technical and mathematical way of determining proper word count on a line…but I digress.

    My point here is that this feature is potentially very valuable. It must be used in moderation though. Usability concerns arrise as well. One major difference between print and web, is that a web browser scrolls. BUT I have hopes for this and hope it will become more of a standard in the future. Even if a bunch of junk comes from it, it merely helps sort out good design from bad… though I should be careful with a wish like that, people start to forget good design 🙁 Anyway, nice article and let’s keep our fingers crossed.

  38. I have an unordered list I needed to dynamically break into 2 columns. This solution works almost beautifully. While it does split the unordered list into two columns it breaks the href tag on the first entry of the 2nd column leaving that particular item unlinked.

  39. I’ve implemented the basic CSS3 multi-column functionality in a “template for the Serendipity blog engine (Serendipity themes)”:http://themes.daves.me.uk. It’s imaginatively called ‘Multi-column’ and of course it only works currently in Firefox. I could implement a javascript solution for other browsers until they deign to support multiple columns. As all the content is generated dynamically, I’ve only used column-gap and column-count but it seems to work well

  40. In the example test case 6 on this site you can see that the list item which goes to the top of the next column, does not work as a hyperlink.
    I am trying to use the script to do a very similar thing, and it does not work on my site either.
    I hope you can fix this, since I would like to use the script very much.

    Best regards,

    Linda

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA