Posted on by & filed under css.

Of all the problems I needed to solve to develop the mobile version of Ibis Reader, I didn’t think I’d need to solve pagination. “WebKit supports CSS3 columns, I don’t have to worry about it.”

My idea was that I’d make the viewport as wide as a single column but force at least 2 columns, and let the user swipe or tap to slide the viewport right and left across all the pages. When I implemented it, it appeared to work great. There was just one problem.

WebKit CSS3 columns are actually broken.

The problem is that elements that are flowed into columns don’t report their position properly. They report their position as if they weren’t in the column at all, but instead had just flowed normally.

This is pretty much a deal-breaker if you want to be able to know what text is on the current “page”, for example, to sync your position across devices.

Here’s a test case that exhibits the problem. I’m requesting the horizontal position of an element that falls in the second column. It should report a value that’s greater than the width of the first column. Instead it reports a tiny value, as if that text were actually positioned up against the left margin.

Chrome, Safari, Mobile Safari, Android

Ironically, Firefox, which lags behind WebKit in its HTML5 support, does the correct thing:

You can download the test case and run it in any browser.

Unfortunately for us, this meant we had to implement pagination entirely in JavaScript. I’ve done this a few times before (such as in the ePub Zen Garden), but that wasn’t with arbitrary HTML. We worked really, really hard to get JS-based pagination to be as accurate and efficient as possible, but it’s still one of the most resource-intensive parts of the app, and a primary reason why it’s not as fast as a native app.

I’ve been told that this bug is fixed in the WebKit source, but since we’re at the mercy of the deployed versions on mobile devices we never further investigated. The moment this fix lands in a consumer browser we’ll switch to supporting it, which should be a huge performance boost.

Update March 8, 2010: Confirmed fixed in WebKit nightly, so eventually this fix should filter down to the mobile browsers.


8 Responses to “CSS columns for ebook text”

  1. Joseph

    I agree — finding the real location of columned elements has been something of a frustration for Monocle too. GetClientRects is promising, but was still erroneous in the last testing I did (a few weeks ago).

    My solution is probably peculiar to Monocle’s column-width/scroll setup, but I found that using element.scrollIntoView then checking scrollLeft gave me at least a useful x coordinate.

    It’s a hack I’d love to dig out, though. Great news that it works in the latest nightly.

  2. Liza Daly

    Oh no, I was experimenting with getBoundingClientRect based on finding it in your code (we only care about WebKit on the mobile devices). So far it was meeting my needs (paired with document.elementFromPoint), but I hadn’t experimented a ton.

    element.scrollIntoView is an interesting idea too — thanks! (When I had a columns implementation it was basically the same as yours.)

  3. Joseph

    Yeah that’s right. The WebKit in 3.1 is from Feb 09, and the implementation landed in WebKit trunk a couple weeks later. I expect it to be in 3.2/4.0 though. For now it’s not something you can rely on — in Monocle I use it only for optimisations.

    Sadly it doesn’t look like the multi-column module is a part of Microsoft’s plans for IE9, so the columnar technique isn’t going to be a cross-platform solution any time soon.

  4. Liza Daly

    It does seem to work in the iPad though!

    (Rather, the same CSS3 columns bug applies, but the getBoundingClientRect() method works as it does on Safari 4.)

  5. bowerbird

    joseph said:
    > Monocle

    i didn’t hear about your debut, joseph. glad to see your effort!