Posts from Wednesday, November 9th, 2005

Multi-Unit Any-Order Columns

Published 18 years, 4 months past

During last week’s workshop in Chicago, I was asked to discuss Alex Robinson’s One True Layout.  This presented a bit of a challenge, since the article and its contents are rather new.  While I’ve read through it all and grasped the main points, I wasn’t entirely sure I grasped the nuances.  For that matter, I’m still not entirely certain that I do.  And I tend to be wary of speaking about things I don’t fully understand.  Still, the audience was interested, so I took the plunge, figuring that I could stick to the bits I knew relatively well.

The Any Order Columns seem straightforward enough, once you get that it’s using margins to shift elements around.  The Equal Height Columns aren’t really, perhaps more properly being called “Extremely Tall But Clipped Columns”, but they simulate the job well enough to count.  And then there is the case of Vertical Grids, which I’m still pondering.

But as an illustration of why I say I’m not sure I grasp all the nuances, it was literally while presenting on this topic during the workshop that I hit on an extension of Any Order Columns (AOC) that allows for AOC to be used with columns of mixed width measures.  It came in response to a question about that very thing.  I’d been showing how to do AOC with columns sized with consistent units, like all with percentage widths or all with pixel widths.  But, an attendee asked, what if you wanted to have one column with an em width and another with percentages?

Say, for example, you wanted the first and second blocks (to use the terminology from Alex’s examples) to be the center and right columns, respectively, and the third block as the leftmost column.  Furthermore, suppose you want the left column to be 10em wide, the center column 40em wide with 1em ‘gutters’, and the right column to be 200 pixels wide.  I’m using pixels because it’s a commonly-used unit, but if it makes you feel better, assume there are Flickr images there or something similar in that column.

All right.  So we have to move the third block leftwards by 40em of center width, 2em of gutters, 10em of the space it will occupy, and 200 pixels of the rightmost column—the second block.  That’s 52em + 200px, which is exactly the sort of thing CSS doesn’t allow for a variety of reasons, some more reasonable than others.  IE/Win allows expressions, but only with a proprietary value syntax that nobody else supports.  And it potentially could be done with JavaScript, which would require pulling some font-size information in order to compute various em widths.

Or… we could relatively position a float, using the float’s margin to handle one of the measures, and the relative positioning to handle the other.  So you start like this:

#block3 {float: left; margin-left: -200px;}

That will get the third block to sit right on top of the second.  That’s taken care of the 200 pixels, but what about getting it the rest of the way?  Add the following:

#block3 {float: left; margin-left: -200px;
  position: relative; left: -52em;}

This puts the third block right where we want it.

There’s one exception: IE5/Mac, which doesn’t pay attention to the relative positioning when the element’s been floated.  So far as I’ve been able to discern, this is the one reduction of browser support from Alex’s original AOC.

With a little bit of math, you can make this work so long as the elements to the left of the shifted column use no more than three different units in their sizing.  To handle two types of units, you could do something like this:

#block1, #block2, #block3 {float: left;}
#block1 {width: 35em; padding: 0 20px; margin-left: 9em;}
#block2 {width: 12em; padding: 0 15px 1em 5px;}
#block3 {width: 8em; padding: 0 0.5em;
   margin-left: -60px; position: relative; left: -56em;}

(code example with browser workarounds)

This approach would permit the ability to drop in pixel-sized decorations, like separators or drop shadows or whatever, while preserving em-width column contents in order to scale with font sizes.

Now suppose you have a mixture of all three unit types, which is a case I didn’t tackle in the workshop.  I might even have said it wasn’t possible to handle, but if I did say that, I was wrong.  With the addition of a negative right margin on the second column, we can handle all three units, as seen here:

#block1, #block2, #block3 {float: left;}
#block1 {width: 50%; margin-left: 11em; margin-right: 1em;}
#block2 {width: 200px; margin-right: -200px;}
#block3 {width: 10em; margin-left: -50%;
  position: relative; left: -12em;}

(code example with browser workarounds)

Note that I’m not saying that you’d necessarily want to mix fixed-width columns with fluid-width columns.  Doing so is a potentially volatile mix when using CSS-driven design, and this technique doesn’t make it any more or less volatile.  If you want to do it, though, this is a powerful approach.

In the examples to which I pointed, I came across some intermittent appearances of the double-margin float bug in IE5.5/Win, though oddly not in IE6/Win.  I didn’t try to work around these inconsistencies beyond using the display: inline hack from Alex’s original examples, but I’m sure they’re surmountable.  It’s probably as good a case as any for using conditional comments to serve up fixes to pre-IE6 versions of IE/Win.

You may have noticed that, if the browser window is reduced in width, the columns start dropping in the two-unit example.  That’s something that could likely be handled with a sufficiently wide container, although doing that risks the dread horizontal scrollbar.  You’d get the same scrollbar with either older CSS layout approaches or with table-driven design, though.

I suspect there are even more combinations and nuances to be found in the AOC technique, and still more in the column and grid ideas Alex has laid out.  Hopefully I’ve made a good start here.  For any omissions or inaccuracies there may have been in my Chicago presentation, I hope the attendees and organizers will accept my apologies.


Browse the Archive