Float Columns in Any Order

Created 2011 February 6. Last modified 2011 July 16.

The idea of using floats for layout is a familiar one. The problem is that we're limited to stacking them to the left or right; there is no proper control over placement...

... until now :) and to-boot the IE 6 and 7 drop floats bug gets fixed too :D

Here's how

By applying this CSS:

.col {float:left;margin-right:-100%;}
.col-a {width:50%;margin-left:25%;}
.col-b {width:25%;margin-left:75%;}
.col-c {width:25%;margin-left:0;}

... to this markup:

<div class="clearfix">
	<div class="col col-a">Main Content (Div 1)</div>
	<div class="col col-b">Sidebar (Div 2)</div>
	<div class="col col-c">Nav (Div 3)</div>
</div>

... we get:

Main Content (Div 1)
Sidebar (Div 2)
Nav (Div 3)

Main Content is in the centre column, Nav is in the 1st column and Sidebar is in the 3rd column.

And if linearised we have Main Content, Sidebar and then Nav as can been seen from the markup.

FTW

With different margin-lefts the position of columns can be changed without touching the markup, win!

The biggest win for me though is when doing Responsive Web Design. I have more options to order the content how I want and more options to control the layout from linearised up to large screen.

Pretty cool huh and it's easy.

Internet Explorer

As with most techniques IE needs a bit of encouragement. The following applies all the fixes needed inside conditional comments, explanations are given afterwards:

<!--[if lte IE 6]>
  <style>
    /* IE less than or equal to 6 */
    .col {
      word-wrap:break-word; /* Expanding Box 1 Fix */
      overflow:hidden;      /* Expanding Box 2 Fix */
      display:inline;       /* Doubled Margin Bug Fix */
    }
  </style>
<![endif]-->

<!--[if lte IE 7]>
  <style>
    /* IE less than or equal to 7 */
    /* A potential and strange bug when using inner divs, fixed by triggering hasLayout */
    .col-inner {display:inline-block;}
    .col-inner {display:block;}
  </style>
<![endif]-->

Expanding Box 1 (IE lte 6)

The problem is that long unbroken words, URLs and preformatted text that are wider than the column will expand the width of the column instead of just visibly overflowing. Solved by forcing unbroken words to wrap.

Expanding Box 2 (IE lte 6)

The problem is that a fixed-width element, like an image, can expand the width of a column instead of visibly overflowing. Solved by setting overflow:hidden which allows a fixed-width element to overflow the column by hiding the overflow.

Doubled Margin Float Bug (IE lte 6)

The problem is that a float with left or right margins will have the margins doubled. Solved by setting the float to display inline.

A Potential and Strange Bug when Using Inner Divs (IE lte 7)

It's likely that inner divs will be used in order to apply padding, margin or background to a column. The problem that arises is to do with a gap or a jog that appears for no good reason, but is repeatable. Solved by triggering hasLayout on the inner div.

Demo

First in source

Second in source

Third in source

First in source

Second in source

Third in source

First in source

Second in source

Third in source

Browser Tests on Demo

Test checks if the layout displays as intended, links are clickable, links are focusable and text is selectable. I plan on doing more tests for fixed width layouts and mixed fluid and fixed layouts.

OK

Windows: Chrome 9, Firefox 1.5, 2.0, 3.0, 3.5, 3.6, 4.0b11; Internet Explorer 8; Opera 8.54, 9.64; Safari 4
OSX 10.5: Camino 2; Chrome 9; Firefox 4.0b10, 4.0b11; Opera 11; Safari 2.0, 2.0.4, 3.04

OK with a little help

Windows: Internet Explorer 5.5, 6, 7. See the page source for more.

Fail

OSX 10.5: Internet Explorer 5.2, I was curious.

Reading

Negative Margins

Sub-Pixel Rounding

The Doubled Margin Float Bug

The Expanding Box Problem

Source Order and Display Order

A Rounding Story

I uncovered/created this technique while working on ZXCSS Layout which got me looking into the grubby bits of web layout.

One such bit was IE6 and 7 dropping floated columns. This happens when a px value like 230.5341 needs rounding to a whole value. IE6 and 7 would round this up to 231. Therefore on occasion too many pixels try to occupy one space and a float is dropped.

Now I'd seen usage of floats with negative margins, applied this and targetted IE6 and 7 floats with margin-right:-1px, which cancelled out any unwanted extra pixels.

Then I thought, What would happen with a margin-right:-100%?

The result was that all the floats appeared to the left seemingly on top of each other. Not pretty, but what if the left margin was used to position them. It worked. I then realised these floats could be positioned in any order.

After the excitement of finding this. I checked to see if there were any obvious bugs, like not being able to click links. So far so good.