News

Create multi-column layouts with CSS

Take advantage of browser support and recreate print style pages using the column-count property.

Create multi-column layouts with CSS

A mainstay of newspaper and magazine print design is the humble column. Columns help to improve the readability of text, ensuring that the consumer doesn’t lose their place in lines of the text that are too long.

For a long time, web designers have attempted to bring this staple typographical design element to the screen, but have always been restricted by the need to set up complicated floating elements, and no support for automatically flowing text content across columns.

A CSS module to support multi-column layouts was first discussed in 1999, so it’s been a long journey to get to the point where we can start to use the properties made available. Thankfully, with the release of Internet Explorer 10, all the major browser vendors will support the standard to a greater or lesser degree

In this tutorial we’re going to examine the primary properties available to achieve multi-column layouts, starting with some basic HTML5 markup. We’ll not only create a flexible layout, but also look at some of the current limitations, and how to best take advantage of the feature today. Finally, we’ll see how you can repurpose your design to support different screen sizes and resolutions.

DOWNLOAD THE COMPLETE CODE

Create your HTML


We’re using a basic HTML5 document with a single article, complete with header and footer. Fortunately, the HTML markup is as basic as you can get; we’ve got a series of paragraphs, a few heading tags and a couple of images. You can either open our start.html document from the resource disc, or use your own content.

Add a stylesheet

We’re going to leave the HTML alone throughout, with all the changes that we make happening in a stylesheet. Let’s create that now by saving a new plain text document into the styles folder as ‘screen.css’. Create a link to it from the HTML document with the code shown below.

001 link rel=”stylesheet” type=”text/css” href=”styles/screen.css” /

Basic properties

We’ll start off by giving our article a bit of basic styling, using typography and spacing, to create the general look and feel of a newspaper. Add the CSS rules below to your stylesheet document to set this up, and preview in your browser. Note that even the most recent web editors don’t tend to fully support columns yet, so you’ll need your browser on hand a lot to test during this tutorial.

001 /* CSS Multi-Column Layouts */
 002 body {
 003 background: #444;
 004 font-family:georgia, times, serif;
 005 font-size: 62.5%;
 006 line-height:1.4em;
 007 }
 008 article {
 009 position:relative;
 010 margin:auto;
 011 width:920px;
 012 padding:20px;
 013 background: white;
 014 box-shadow: 0px 0px 10px #333;
 015 }
 016 article p {
 017 font-size: 1.2em;
 018 line-height: 1.6em;
 019 }

Introducing columns

CSS allows you to set up columns in any block-level element by using the column-count property. The column-count property accepts a number representing the number of columns you’d like the element to be split into. Try adding the code below to your existing article rule in the stylesheet so you can see this in action:

001 column-count: 2;

Vendor prefixes

As with many of the CSS3 properties and modules, columns currently need you to employ browser-specific vendor prefixes to call and set the property. We’ll need to duplicate our rules using -ms-, -webkit-, -moz- and -o- before each property to target the big five – Internet Explorer, Safari/Chrome, Firefox and Opera – respectively.

001 -webkit-column-count: 2;
 002 -moz-column-count: 2;
 003 -o-column-count: 2;
 004 -ms-column-count: 2;
 005 column-count: 2;

Set the gutter width

You can manually set the width of the gap between columns using the column-gap property. If you’d like a wider gap between columns, set a higher column-gap value or to achieve closer columns set it lower. If you omit the column-gap property, the browser will automatically format a gap for you.

001 -webkit-column-gap: 1em;
 002 -moz-column-gap: 1em;
 003 -o-column-gap: 1em;
 004 -ms-column-gap: 1em;
 005 column-gap: 1em;

Set the column width

Similarly, you can control the width of your columns using the column-width property. As with the column-gap property, if you don’t set this explicitly the browser will calculate the value for you automatically. If you only set the column width, the gap will be calculated to fit the width of the container, and vice versa. If you specify a width that’s too big for the element, the browser will override your setting.

001 -webkit-column-width: 20em;
 002 -moz-column-width: 20em;
 003 -o-column-width: 20em;
 004 -ms-column-width: 20em;
 005 column-width: 20em;

A word on limitations

You can’t currently set different widths for different columns, so if you want to have one wide column and two narrow columns, you’ll have to nest elements inside columnar layouts. This limitation may be addressed by the W3C in the next iteration of the CSS Columns module.

Flowing content

By default your content will flow automatically from one column to the next, and the length of the overall element (in our case an article tag) will be adjusted to fit a balanced fill of columns. This ensures the final product looks tidy and clean. You can overwrite this setting with the column-fill property.

001 -webkit-column-fill: balanced;
 002 -moz-column-fill: balanced;
 003 -o-column-fill: balanced;
 004 -ms-column-fill: balanced;
 005 column-fill: balanced;

Setting up our layout

Let’s take what we’ve got so far and apply it to our article to create a nice multi-column layout. We’ll start off with four columns, and allow the content to fill the columns automatically. We will also make our first paragraph a bit bigger, so as to act as an introduction to the main piece.


Test and review

If you load up the page inside your browser now, you should see a nicely balanced four-column layout with text balanced nicely between the four columns. You’ll notice that some of the text should perhaps flow across multiple columns though, especially in the header. Let’s address that next.

Spanning columns

Headings and pull quotes can be set to span multiple columns by using the column-span property. Currently this property only supports two values: none or all. This means that your content will either break out and flow across all the columns in your layout, or will conform to the column layout. Add the code below to see this in action:.

001 article header {
 002 position: relative;
 003 display: block;
 004 -webkit-column-span:all; column-span: all;
 005 border-bottom: 2px solid #333;
 006 }
 007 article header h1 {
 008 font-size: 9.5em;
 009 line-height: 1em;
 010 font-weight: bold;
 011 text-transform:uppercase;
 012 margin:0;
 013 padding: 0;
 014 }
 015 article header h4 {
 016 text-align: right;
 017 margin: 0;
 018 padding: 0;
 019 }

Images and columns

You’ll notice that the images in our original markup are rendering perfectly inside the column width. This would be the case regardless of the size of the image, so long as you leave the width and height attributes out of the tag. Doing so means you can use images just as you normally would, without worrying about how they are going to fit into variable-size columns.

Breaking columns with spanned elements

About halfway down our article we’ve got an aside element, which is acting a bit like a pull quote. We’re going to use this to break up our columnar layout by applying the column-span property to the aside element. While we’re at it, we’ll add a border to the top and bottom to help separate the element visually.

001 article aside {
 002 position: relative;
 003 display: block;
 004 font-size: 2.2em;
 005 line-height: 1.8em;
 006 font-style: italic;
 007 -webkit-column-span:all;
 008 column-span: all;
 009 border-top: 2px solid #333;
 010 border-bottom: 2px solid #333;
 011 margin-bottom: 20px;
 012 }

Column behaviour

Reload the page in your browser to see the breakout aside in situ. Notice that the columns now fill left to right above the /aside, aside, and then pick up again beneath it with the content that appears after it. This is important behaviour to recognise when using columns – any element that spans columns breaks the structure.

Applying column rules

As well as providing a border to the spanning elements, we can also apply a defined visual separation to the columns themselves by using the column-rule property. This accepts arguments similar to the border property in CSS. Try adding the code below to your article rule in the stylesheet, to see an example of column rules in practice.

001 -webkit-column-rule: 1px solid #333;
 002 -moz-column-rule: 1px solid #333;
 003 -o-column-rule: 1px solid #333;
 004 -ms-column-rule: 1px solid #333;
 005 column-rule: 1px solid #333;

Style the footer

We’ll use some of the properties we’ve covered above to style the footer element, which is going to round off our article nicely. First it should span the columns, have a border top and bottom, and we’ll add some margin and padding to help it get some distance and sit apart from the content a little. Add the rule below to put this in place.

001 article footer {
 002 position: relative;
 003 display: block;
 004 -webkit-column-span:all;
 005 column-span: all;
 006 border-top: 2px solid #333;
 007 border-bottom: 2px solid #333;
 008 padding: 10px;
 009 margin-bottom: 20px;
 010 }

Preview and test

We’ve just about completed our basic column layout now, so before we attempt to make it flexible enough to work across different resolutions on multiple devices, it’s a really good idea to preview it in your browser, and then make sure it works across all the common browser options you plan to support.

Always remember that you can use Modernizr to test for column support and provide a fall-back for
older browsers.

Fluid layouts

Up until now we’ve had a fixed-width for our article, set at 960px. We’ll change this by using @media queries inside our stylesheet. The only element that needs to change is the article rule, with the width and number of columns adjusted to suit the screen width. Add the code below in place of the existing article {} rule to start. (download full code)

×