CSS3: The Multi Column Layout and How it Will Change Web Design

January 20, 2012 at 5:35 pm By
Demo

Multiple Columns

What is strikingly odd about web design is just how difficult it can be to make a multiple column website. For the last 15 years we’ve been designing websites like newspapers and magazines, consisting of many columns, and it’s been working out pretty well. The tools we use, however, haven’t changed that much since then as regards layout. For example, in CSS we have to use the float property which can be quite bothersome and even worse, we may even resort to an old status quo: using tables.

That’s why the CSS3 Multi Column Module is perhaps one of the most interesting and exciting things that has happened to CSS in a long time. It’s not a gimmick or design trick like box-shadow or animation. It’s a real, tangible device which we can use to make designing websites easier. For a long time it was an unreachable goal. Something coming in the future, but not right now. That is no longer the case. All the main browsers support at least a few of the multi column layout module, and at least, enough to make a functioning website with it. Check out the demo to see it in action

Support

Webkit Gecko Trident Presto
columns Experimental Experimental Experimental Supported (2.8)
column-count Incorrect
column-width Supported (2.8)
column-gap
column-rule
column-span Not Supported
column-fill Not Supported
break-before Experimental Not Supported
break-after
break-inside Not Supported

Opera (Presto) is pushing ahead with support of this module. The other browser vendors have also implemented experimental versions of this perhaps incase the specification changes.

What it does

Columns are a way of organizing content. The CSS specification says that this will be simplified as screen size becomes smaller, by default. This is apparent in the implementations in many browsers. As a quick beginners example, lets say we have this syntax:

<style type="text/css">
div {
	column-width: 10em;
	column-gap: 2em;           
	column-rule: 4px solid blue;  
	padding: 5px;
}

p {
	padding: 0;
	margin: 0;
	font-family: Arial, sans-serif;
	text-align: justify;
	font-size: 14px;
	line-height: 20px;
}

</style>

So what we’re saying here is that the div will be separated into columns that will be 10em wide. We could use pixels too! Then we say the gap between the columns. Then we put a rule between the columns which will appear in the middle of the 2em. In other words, it goes 1em, border, 1em. Here are some images showing how screen size affects number of columns:

Wide Screen

Normal Screen

Small Screen


This is all automatic! So instantly, I’m sure you can see the applications of this for mobile and screen size orientation. Whereas before we used a lot of media tags to alter websites according to size, we could see more use of this when it reaches full implementation in browsers.

So how exactly does all of this work?

A Rundown of the Properties

columns

A short syntax for the column-count and column-width

columns: <column-width> <column-count>

column-count

The number of columns! The implementation of this is strange. In Opera column-count seems incompatible with column-width. Column-width seems to override column-count whereas the specification says that if both are defined, column-count should define the maximum number of columns. Webkit and Gecko have the correct implementation of these features.

column-count: 5; /* For 5 columns */

column-width

The optimal column width. If the window is too small, the columns may be smaller. Conversely, if the window is too wide it might be larger!

column-width: 15em;

column-gap

The gap between columns.

column-gap: 2em;

column-rule

The rule (or line) between columns. This works the same as a border. For example, a 2px solid black border would be made like this:

column-rule: 2px solid black; 

column-span

This is a pretty cool property. Lets say you have a header like this:


<div>
	<p>
		Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur consectetur mauris sit amet felis tincidunt vel auctor velit hendrerit. Fusce at libero vitae lectus placerat lacinia sit amet non sem. Proin malesuada consequat tortor, nec placerat ante mollis vitae. Mauris nec ante orci. Nullam interdum molestie lorem sed fringilla. Integer scelerisque felis et tortor porta fermentum. Morbi pharetra purus quis nulla posuere sed suscipit ligula blandit. Suspendisse risus urna, hendrerit sed aliquam eget, egestas vitae elit. 
	</p>
	<h2>
		Some Title
	</h2>
	<p>
		Mauris viverra porta sollicitudin. Sed semper, metus sagittis congue ultricies, mi neque dapibus nisl, non placerat sapien mauris vitae libero. Vestibulum fringilla aliquet diam, sit amet dapibus urna interdum eget. Duis laoreet sapien ut elit tempor ac lobortis nibh commodo.
	</p>
</div>

In the middle of the content. You want it to go through all columns. Well you’d just do this!

h2 {
      column-span: all;
      background: #eee;
}

Which will give you this:

column-fill

The column-fill property is perhaps a bit ambiguous as compared to the other properties. It has two properties, ‘balance’ or ‘auto’.

In continuous media, this property will only be consulted if the length of columns has been constrained. Otherwise, columns will automatically be balanced.
In continous media, this property does not have any effect in overflow columns (see below).
In paged media, this property will only have effect on the last page the multicol element appears on.

break-before/break-after/break-inside

This is for paged media. It defines when the columns should be broken, i.e. when a new column should start. These are pretty useless at the moment because of lack of support. These are applied to other elements, like an h2 or img. For example if we did this:


h2 {
      background: #eee;
      break-before: column;
}

It would force a new column to start before the h2 element. I think from there you can extrapolate how the other elements work. Here’s a summary of the various properties you can apply:

break-after: auto | always | avoid | left | right | page | column | avoid-page | avoid-column;
break-before: auto | always | avoid | left | right | page | column | avoid-page | avoid-column;
break-inside: auto | avoid | avoid-page | avoid-column;

This is actually really useful. It lets us turn columns into a more content aware layout.

A Working Example

This is a little real world example I’ve put together. I put together a lot of random content into a div, to test the behaviour:


<div>
	<p>
		<img src="column.jpg" alt="" />
		Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur consectetur mauris sit amet felis tincidunt vel auctor velit hendrerit. Fusce at libero vitae lectus placerat lacinia sit amet non sem. Proin malesuada consequat tortor, nec placerat ante mollis vitae. Mauris nec ante orci. Nullam interdum molestie lorem sed fringilla. Integer scelerisque felis et tortor porta fermentum. Morbi pharetra purus quis nulla posuere sed suscipit ligula blandit. Suspendisse risus urna, hendrerit sed aliquam eget, egestas vitae elit. 
		<hr class="double" />
	</p>
	<h1>
		Lorem Ipsum!
	</h1>
	<p>
		Mauris viverra porta sollicitudin. Sed semper, metus sagittis congue ultricies, mi neque dapibus nisl, non placerat sapien mauris vitae libero. Vestibulum fringilla aliquet diam, sit amet dapibus urna interdum eget. Duis laoreet sapien ut elit tempor ac lobortis nibh commodo.
	</p>
	<p>
		Mauris viverra porta sollicitudin. Sed semper, metus sagittis congue ultricies, mi neque dapibus nisl, non placerat sapien mauris vitae libero. Vestibulum fringilla aliquet diam, sit amet dapibus urna interdum eget. Duis laoreet sapien ut elit tempor ac lobortis nibh commodo.
	</p>
	
	<hr class="single" />
	<h2>Dolor Sit Amet</h2>

	<p>
		Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur consectetur mauris sit amet felis tincidunt vel auctor velit hendrerit. Fusce at libero vitae lectus placerat lacinia sit amet non sem. Proin malesuada consequat tortor, nec placerat ante mollis vitae. Mauris nec ante orci. Nullam interdum molestie lorem sed fringilla. Integer scelerisque felis et tortor porta fermentum. Morbi pharetra purus quis nulla posuere sed suscipit ligula blandit. Suspendisse risus urna, hendrerit sed aliquam eget, egestas vitae elit. 
	</p>
	<p>
		Mauris viverra porta sollicitudin. Sed semper, metus sagittis congue ultricies, mi neque dapibus nisl, non placerat sapien mauris vitae libero. Vestibulum fringilla aliquet diam, sit amet dapibus urna interdum eget. Duis laoreet sapien ut elit tempor ac lobortis nibh commodo.
	</p>
	<hr class="single" />
	<h2>Consectetur Elit</h2>

	<p>
		Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur consectetur mauris sit amet felis tincidunt vel auctor velit hendrerit. Fusce at libero vitae lectus placerat lacinia sit amet non sem. Proin malesuada consequat tortor, nec placerat ante mollis vitae. Mauris nec ante orci. Nullam interdum molestie lorem sed fringilla. Integer scelerisque felis et tortor porta fermentum. Morbi pharetra purus quis nulla posuere sed suscipit ligula blandit. Suspendisse risus urna, hendrerit sed aliquam eget, egestas vitae elit. 
	</p>
	
</div>

Then added a little bit of styling for the various elements:


/* The two line breaks */
.double {
	margin: 10px 0 0 0;
	height: 20px;
	border: 0;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;	
}

.single {
	border: 0;
	border-top: 1px solid #ddd;
	padding: 0; margin: 0;
}

/* Header styling */
h1, h2 {
	font-family: Georgia, serif;
	font-weight: lighter;
	font-style: italic;
}
 
/* Content styling */
p {
	padding: 0;
	margin: 0;
	font-family: Georgia, serif;
	text-align: justify;
	font-size: 14px;
	line-height: 20px;
}

img {
	border-radius: 5px;
	max-width: 20em;
	float: left;
	margin: 0 20px 10px 0;
	border: 1px solid #999;
	box-shadow: 0px 0px 10px rgba(0,0,0,0.2);
}


p {
	padding: 0 0 15px 0;
}

And finally made the columns work! Various browser prefixes were required, but there is no reason why this shouldn’t work in the latest versions of all browsers.


div {
	-webkit-column-width: 20em; /* 20em wide */
	-webkit-column-gap: 2em;  /* 2em gap */
	-webkit-column-rule: 1px solid #eee;   /* 1px border between columns */
	-webkit-column-count: 3; /* 3 columns max! */

	-moz-column-width: 20em;
	-moz-column-gap: 2em; 
	-moz-column-rule: 1px solid #eee;  
	-moz-column-count: 3;

	-ms-column-width: 20em;
	-ms-column-gap: 2em; 
	-ms-column-rule: 1px solid #eee;  
	-ms-column-count: 3;
	
	column-width: 20em;
	column-gap: 2em; 
	column-rule: 1px solid #eee;  
	column-count: 3;
	
	padding: 5px;
}

And that’s it! Click below to check out the demo. I hope you’ve enjoyed this tutorial!