How to show/hide content which uses CSS3 columns

I like CSS3 columns. They're an interesting solution to the problem of columnar content on the web. Not quite as powerful as, say, a Quark-like flowing of content from one block element to another; but still preferential to the hacks we've used in the past.

One problem with CSS3 columns is that, if they're applied to an element whose height changes, then the browser updates the flow of text in real time, to only ever hide the bottom-most child elements. If you combine this behaviour with jQuery's .slideToggle() events, it leads to a kind of frantic scramble of your content as it tries to keep up with the rapidly closing or opening container element.

In case that's not clear, here's an example below. I've set up a container div with four-column layout, and inside it I've just put a number of unordered lists. Below it is a button, which will let you toggle the visibility of the container div.

  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three

The behaviour is probably browser-specific (and won't work on old browsers at all) but you should get a feel for the content scurrying around inside the container div as it opens and closes. Why browsers render like this is entirely understandable in static scenarios, but still unsightly when the element height is changing rapidly.

How can you fix this? By adding an extra wrapper div. The wrapper div carries the show/hide behaviour, leaving the inner div to continue to carry the columnar behaviour. Because show/hide works by chopping off any elements within it, then the columnar div is no longer resized by the Javascript action, and so the columns inside are merely chopped off as well, without any reflowing of content.

Here's an example of this fix:

  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three
  • One
  • Two
  • Three

It's not perfect, yet: as you can possibly spot, the container div is briefly very tall during the reveal action, before settling on the right height. Either jQuery is miscalculating element heights somehow, or there could be some much deeper concern for browsers over how the height of elements' contents are calculated: do feed back in the comments if you've any ideas. But at least my show/hide effects don't look like a picnic overrun by rats any more.