Monthly Archives: July 2013

How I made a website behave more like a book

I’ve been idly sketching ideas vague ideas for a redesign of my blog this week, and found myself heading down a well-worn route. A blog (I said to myself) is really nothing more than a collection of titles and text — maybe a few images thrown in here and there, probably a datestamp, but that’s basically it. Focus on the content.

But when I started sketching how that sort of content-focused site might look, I found that it all started to look a little familiar. Andybudd.com. Zeldman.com. Medium.com. Any of a dozen Squarespace templates. There was obviously a limit to what one could do with nothing but a title and a handful of paragraphs.

Nature Paint screenshot

Then, in an interview with Cole Henley in .NET magazine, I spotted a screenshot of the Nature Paint website. Although Cole has actually used a variety of different templates to build that site, it was the two-column layout that caught my eye. Perhaps that could be the difference, the tweak I was looking for to turn a blatant rip-off into something a little bit special.

Multiple columns with CSS3

Turning plain paragraphs into multi-columnar layouts is pretty simple with CSS3 now. The column-count, column-width and column-gap properties let you create equally spaced, equal height columns within an element, and you can break up the flow through judicious use of the column-span or column-break-before properties. You can even add nice newspaper-style dividing lines with the column-rule property.

However, there is one enormous problem with trying to display multiple columns of text on the web: viewport size. In a magazine or newspaper, you can hold the entire page in front of you, and your eye can easily move from the bottom of one column to the top of the next. But on the web, it is entirely possible that your reader has scrolled so far down to read a longer piece of writing that the top of the next column is off the visible page. Breaking off mid-sentence to scroll back up to find the next column is not an optimal reading experience. Overflowing columns

I started to draw up a list of requirements for a solution.

Recipe for a pleasant multi-column read

When you read a book, you are effectively reading a double-spread page with two columns of text. You read the left-hand side, then you read the right-hand side, and then you turn to the next page. Magazines might have four or more columns; newspapers up to seven or eight. But the principle is always the same — your eye is guided from column to column across the page, until you need to move onto the next. So, if on the web you are reading a lengthy piece of writing consisting of many many paragraphs, what we need to do is break it up into chunks that fit nicely into the viewport window. The viewport becomes your double-spread book page, and readers can comfortably read each collection of blocks of text before scrolling down to the next ‘page’ of content. I experimented with a few different methods of achieving this, and eventually arrived at a relatively simple JavaScript solution: View Demo page

We declare a single class to handle the column settings:

This class is applied to the container element, so that even if the script doesn’t run we still get something approximating what we intended.

The script then loops through all of the child elements of the container, moving them in batches into new containers, which each get the same .columns class applied to them — these represent the ‘page’ we discussed above. The size of each ‘page’ is determined through a combination of the viewport size, the font size, and the line height of the site. By supplying a list of those elements that should ‘break out’ of the multi-column ordering, we can make sure that the intended flow of the article is preserved. It’s not perfect, but it prevents columns overflowing the viewport and (I think) makes for a more pleasant, book-like, reading experience.

In browsers that don’t support CSS3’s column properties, the script has no effect, since both ‘before’ and ‘after’ states use the same declarations. (If I was using Modernizr I would probably check for support of those properties first, and not run the script at all if they were not present.)

Improvements and feedback

The script makes a reasonable job of breaking up the content into roughly the right-sized blocks for the viewport, but I’m sure it could be made a lot more accurate than I managed with my rusty maths. It also need to be made a little more flexible in terms of coping with different types of the same content (e.g. inline images and larger full-width pictures), and I can imagine that adding some basic keyboard navigation would make for an even more relaxed read.

I appreciate that this isn’t an implementation that is going to be useful for very many other people, but it was fun to figure out, and if you do happen to use it or have any suggestions for improvements, let me know.