Multiple columns using CSS3

Published
Written by
John Kavanagh

Whilst columns have been a staple of typography layouts since the advent of print, it hasn't been until relatively recently that the same has been available on the web.

Typography layout wireframe

Columns in typography have always been a design feature implemented for simple reading ergonomics1:

  • If lines of text are very short, then text becomes hard to read as you are forced to constantly jump from one line to the next;
  • If lines are very long then it becomes difficult to keep track of your line whilst moving from the end of one to the start of the next.

For best legibility it is widely accepted that the optimum line length is roughly 60-80 characters, hence newspapers using columns. Despite this, in web development there has not - until recently - been any way of including flexible column layouts (outside of page structures using block-level elements, floats, or - at one time - even tables).

Front-end web developers are an adaptable and creative bunch: we have been working around limitations in specification and browser support to implement column-based layouts since since stylised markup was first available. However, these have always been at a compromise and are made much more complex with the wide-scale support of responsive/adaptive layouts (where it isn't know ahead of time where a column break should occur).

It isn't surprising that when developers post questions about columned content (like this recent discussion on Reddit) the default answer is often a variation on: use set-width elements, float them up against one-another - the method that has been ingrained, tried-and-tested since the decline of table-based layouts.

It has always been a personal gripe that there isn't an easier way to implement columns given how fundamental they are in print media.

Introducing CSS Multi-columns

Although the CSS Multi-column Layout Module specification has been around since April 2011 (six years ago), browser uptake has been relatively slow (the biggest surprise being Microsoft's early support in IE10) and is still fragmented by vendor prefixes. At present, global browser support (both full, and partial - via prefixes) is at 85.86%2 so it is certainly something worth becoming familiar with.

There are a number of different options available (and each of which can be overridden individually for responsive behaviours - see my About page for an example of this), but as with most other properties at least some of these (but not all) can be combined into the single columns short-hand property:

columns: auto|column-width column-count|initial|inherit;

For example, the code below will split the content of the div into four columns, each 200px wide:


.columned{
	columns: 200px 4;
}

This is the equivalent to:


.columns{
	column-width: 200px;
	column-count: 4;
}

There are a number of other options also available within this module, although at present they are inaccessible via short-hand so need declaring independently, these are:

  • column-count: the number of columns to display.
  • column-gap: the gap (gutter) between columns - declared as a CSS value (px, em, percentage, etc).
  • column-width: this is the suggested column width although declared as a CSS value, it isn't absolute. The browser will use this value - if provided - as a baseline for its own calculations.
  • column-rule-width
  • column-rule-style
  • column-rule-color: this, combined with the previous two allow you to include a border between columns using border style properties.
  • column-span: apply this to an element within your columns to force it to span multiple columns; much like col-span in table markup.
  • column-fill: used to define how columns fill the available space.

It is worth mentioning that the last three properties (column-rule, column-span, and column-fill) are still quite unsupported: starting at IE10 for Microsoft browsers.

A word about fallbacks

However you choose to use CSS columns, at the moment you will also need to use vendor prefixes for Mozilla (-moz-) and WebKit (-webkit-) browsers to capture as much support as is possible. Using the example from above, your final code would look something like this:


.columns{
	-webkit-column-width: 200px;
	-webkit-column-count: 4;
	-moz-column-width: 200px;
	-moz-column-count: 4;
	column-width: 200px;
	column-count: 4;
}

Do also bear in mind that - depending on your website's audience - there is a high chance that people will visit using a browser that doesn't support CSS Columns at all, so it is important that you consider how the page will look to those users. They will simply see one large block of text and - for more - that might be a suitable fallback without further work.

However, for me personally it seems to go to these lengths and then not optimise legibility for everybody. I achieve this by using feature-detection from the Modernizr JavaScript library, which injects the class .no-csscolumns into the <html> element so that you can then define a narrower width for your columned content (and avoid overly-long lines of text):


.columns{
	-webkit-column-width: 200px;
	-webkit-column-count: 4;
	-moz-column-width: 200px;
	-moz-column-count: 4;
	column-width: 200px;
	column-count: 4;
}
.no-csscolumns .columns{
	max-width: 80%;
}

Columns in page layout vs. page content

Aside from all the usual cautions regarding backwards compatibility, fallbacks, and vendor-prefixes, there is one final thing for me to mention: CSS Columns should not be considered a tool for layout or page structure (we have Flexbox for that - although support is still currently sparse3). This doesn't replace all of the CSS tricks and tools that have been created for placing website elements into page layouts, but simply offers a much easier method of placing large blocks of text into equi-width, equi-spaced, columns for legibility and/or design purposes.

Comments powered by Disqus
Top