Source Ordered Columns

Return to p.i.e.


So you want a three column layout, and the footer must stay below the cols no matter which one is longest. Not too tuff, just have a static col, and two cols floated left and right, then 'clear' the footer. The longest col will always keep the footer pinned to its bottom edge.

However, since the floated cols must precede the static col, the middle static col is always last in the source code. This is undesirable because if the css is not used (text browsers, etc.), then the cols don't appear in the correct order. A more accessible way would be to place the cols in the preferred source order, and then force them into the desired screen order. But how?

It turns out that with a small amount of extra float trickery we can do just that.
See those colored columns below?

Header <h2>

One One One One One One One One One One One One One One One One One One One One One One One One One One One One
Test link

Two Two Two Two Two Two Two
Test link

Three Three Three Three Three Three Three Three Three Three Three
Test link


Clearing Header <h3>

One One One One One One One One One One
Test link

Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two
Test link

Three Three Three Three Three Three Three Three Three Three Three
Test link


Clearing Header <h3>

One One One One One One One One
Test link

Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two
Test link

Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three
Test link

Clearing Footer (p.clearfooter)

If you sneak a peek at the source, you will see that the cols are in the same order as they are on screen. That is, the left col is first and the right col is last. The three column-groups are identical except for differing amounts of text. Observe how the footers always stay pegged on the bottom of the longest col.

The Method

The ordering is achieved by wrapping a left-floated box around the first and second cols in the source. (blue and green), and left-floating the first col (blue) within that invisible floating wrapper.

Get it? The wrapper is floated, so in the source it comes first, (as a float must), and inside it the floated first col also comes first, becoming the first col to appear in the source. The other col in the wrapper (green center col) is next, and the right col (red) following the wrapper, comes last.

Something more to consider

There's no reason the first col must be floated left, or the wrapper for that matter. By making the float direction on the first col 'right' instead of 'left' (along with its associated margin value on .second-col), we can put .first-col into the center position, with .second-col on its left and .third-col on the right, something highly desirable I'm told.

Header <h2> see demo in isolation

One One One One One One One One One One One One One One One One One One One One
Test link

Two Two Two Two Two Two Two
Test link

Three Three Three Three Three Three
Test link


Clearing Footer (p.clearfooter)

  Minimal HTML for the '2 1 3' demo above:

<h2>Header</h2>

   <div class="float-wrapper">

     <div class="first-col">
    <p>One One One One One One One One One</p>
     </div>

     <div class="second-col">
    <p>Two Two Two Two Two Two</p>
     </div>

   </div>

 <div class="third-col">
<p>Three Three Three Three Three</p>
 </div>

<p class="clearfooter">Clearing Footer</p>


  The CSS:

.float-wrapper {float: left; width: 66%;}
     /*** This can be floated left or right ***/

.first-col {float: right; width: 50%;}
     /*** This can be floated left or right ***/

.second-col {margin-right: 50%;}
     /*** This gets margined the same direction 
        as div.first-col gets floated ***/

.third-col {margin-left: 66%;}
     /*** This gets margined the same direction 
       as div.float-wrapper gets floated ***/ 

.clearfooter {clear: both;}

 p {padding: 10px;}

What you need to know

By selecting the direction to float .first-col, you can choose either the first or second column to place in the center screen position. Further, if .float-wrapper is reversed as well, the column screen order can be 3, 2, 1, or 3, 1, 2.

If you want to vary the 'widths' of the cols, remember that the non-floated 2nd and 3rd cols get margins with a length equal to the width on the associated float. (see code above)

The paragraphs are not there just to be accessible. It's also because using margin, borders, or padding on the column elements themselves is 'difficult'. Don't let me stop you tho, knock yerself out. But, know that doing so will lead into a morass of browser variances, bugs, and to top it all, the IE box model. I'm talking Hack City, folks. Go there only with eyes wide open. Otherwise, use nested <p>'s (or whatever) to hold and style the col contents.

Padding, borders, and horizontal margins may be safely placed on the <p>'s, but vertical margins will show some variance between browsers, and will require hacking in order to be (semi)consistent. Op6 is the only major Windows browser that gets these vertical margins completely correct. Op7/beta does not.

IE6 will display very buggily if these demos are given backgrounds (green BG's), unless 'position: relative' is applied to certain elements. See the source for details on these hacks. Also, Mozilla and N6/7 will sometimes show a 1px gap between the 2nd and 3rd cols in the first two demos, due to 'rounding errors'. The width/margin values on these cols have been tweaked to eliminate the gaps at the main resolutions, but will still show at intermediate screen widths. For more detail, check out this demo.

Danger, Will Robinson! Danger danger...

This layout involves floats, and oversize floats will 'wrap' underneath, shattering the layout. Should there be content in a col that is too wide to fit, the results are 'unpleasant', to say the least. Opera, and 'Gecko' based browsers (N6/7, etc.) will just make the wide content overlap whatever is to the right. Not so in IE. (It figures)

IE/win has the unhappy habit of 'enlarging' any container that has such oversize content. Normally that behavior is just irritating, but in this case, enlarging the cols can result in float wrapping, wreaking havoc on what used to be a 3-col layout. IE5/mac also breaks, in a different yet strangely similar manner. Be very careful about including content other than text. Long web addresses often cause this sort of problem, because they don't have spaces that allow text wrapping.

The IE 3px text jog rears its ugly head

If you implement this layout, you may notice (in IE) a strange little flaw in the left-justification of text in one or two spots. As the left edge of the text block runs down the col, it will suddenly 'jog' to the left slightly, producing an unsightly "disturbance in the font". I have a demo prepared that explains this in more detail. In essence, a non-floated element following a float may show the jog.

This jog may be easily squelched by applying 'width: 100%' to the 2nd and 3rd cols (but with no margins). IE makes these static cols fill the available space next to their respective floats, but without the jog.

Unfortunately, this behavior totally violates the W3C specifications concerning float behavior, so using this method will totally break any other browser that tries to parse it. I have yet another demo explaining said IE misbehavior.
(This IE stuff is getting really tiresome)

So is that it? Internet Explorer staggers triumphant?

Heck no! Luckily there is a way to prevent these proprietary IE behaviors. Simply make all the cols into floats. Boy, that was easy! Okay okay, so it isn't that easy, but it is doable.

The all-float three-ordered-cols method

Since floats induce the 3px jog, but don't themselves show the jog, an all-float column layout avoids the whole problem. The idea is to float the 1st and 2nd cols opposite each other, keeping them in the floated wrapper, and also floating the 3rd col opposite the wrapper. If all the elements are floated, there are no 'static' cols that must come last, so any col may appear in any screen position. Total control.

This control comes at a price, however. Floats must have 'widths', unlike the static cols. If the elements are all given percentage widths, as in the demos above, some browsers may wrap anyway, even tho they shouldn't. The above mentioned rendering error associated with percentages (and EM's), may make an element 1px too wide, causing a wrap.

So the col widths must be fudged downwards (to prevent wrapping), which causes smallish gaps between the cols. If the cols have no backgrounds, the gaps won't be noticable and the 3px jog will be gone. Could be a keeper.

Note: I also added side borders and margins to this demo (.demo-allfloat), just because I could (but see note below for IE5.5 caution with borders and margins).

Header <h2> see demo in isolation

One One One One One One One One One One One One One One One One One One One One One One One One
Test link

Two Two Two Two Two Two
Test link

Three Three Three Three Three
Test link

Clearing Footer (p.clearfooter)

  Minimal HTML for the 'all-float' demo above:

<h2>Header</h2>

   <div class="float-wrapper">

     <div class="first-float">
    <p>One One One One One One One One One</p>
     </div>

     <div class="second-float">
    <p>Two Two Two Two Two Two</p>
     </div>

   </div>

 <div class="third-float">
<p>Three Three Three Three Three</p>
 </div>

<p class="clearfooter">Clearing Footer</p>


  The CSS:

.float-wrapper {float: left; width: 66%;}
     /*** This can be floated left or right ***/

.first-float {float: right; width: 49%;}
     /*** This must be floated opposite 
		to .second-float ***/

.second-float {float: left; width: 49%;}
     /*** This must be floated opposite 
		to .first-float ***/

.third-float {float: right; width: 33%;}
     /*** This must be floated opposite 
		to .float-wrap ***/ 

.clearfooter {clear: both;}

 p {padding: 10px;}

What you need to know

If you happen to want the 3rd col in the center screen position, just make the wrapper enclose the 2nd and 3rd cols, rather than the 1st and 2nd. Then the proper float directions will easily center the 3rd col.

This all-float layout requires two bug fixes to cater for IE. First, in order not to be buggy, IE6/win needs 'position: relative' applied to the demo. This induces more buggyness that must be fixed by giving 'position: relative' to both the wrapper, and to the third floated col as well. (see source)

The second is that IE5.x/win will break, due to its habit of considering a default width of 'auto' to mean "the viewport width". It is fixed by applying 'width: 100%' to the demo, but beware! IE6 will break upon seeing this, so the '100%' must only be seen by IE5.x/win. This is done by use of a hack (see source). If the side borders and margins are avoided, then this hack is not needed.

Since the layout uses bi-directional nested floats, caution should be taken when adding further floats or positioned elements, lest you summon up some hideous Überbug. Test, test, and test again.

You say you want a 'pixel sized' layout?

Well alright then! The fact is that making this layout 'rigid' eliminates the small gaps seen in the last example. Also, I have altered the column 'width' values in the layout, again just because I could. Take a look.

Header <h2> see demo in isolation

One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One One
Test link

Two Two Two Two Two
Test link

Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three Three
Test link

 

Clearing Footer (p.clearfooter)

Minimal HTML for the 'rigid-all-float' demo above:

  <div class="rigid">

<h2>Header</h2>

   <div class="float-wrapper-rigid">

     <div class="first-float-rigid">
    <p>One One One One One One One One One</p>
     </div>

     <div class="second-float-rigid">
    <p>Two Two Two Two Two Two</p>
     </div>

   </div>

 <div class="third-float-rigid">
<p>Three Three Three Three Three</p>
 </div>

<p class="clearfooter>Clearing Footer</p>

  </div>


  The CSS:

.rigid {width: 600px; margin: 0 auto;}

.float-wrapper-rigid {float: left; width: 450px;}
     /*** This can be floated left or right ***/

.first-float-rigid {float: right; width: 300px;}
     /*** This must be floated opposite 
		to .second-float ***/

.second-float-rigid {float: left; width: 150px;}
     /*** This must be floated opposite 
		to .first-float ***/

.third-float-rigid {float: right; width: 150px;}
     /*** This must be floated opposite 
		to .float-wrap ***/ 

.clearfooter {clear: both;}

 p {padding: 10px;}

What you need to know

IE5.5 and IE6 can be buggy with the above 'width-defined' layout, if the cleared footer is given a background. Even 'transparent' or 'inherit' applied to the cleared element background will induce this bug. It's fixed by providing a 'line box' after the 3rd col and just before the clearing div. A <p> will do this, as will a div containing at least one inline element.

However, this rigid layout does NOT suffer from the IE 'demo background' bug mentioned before, so you can have a BG on this layout without hacking for IE6, thanks to the 'width' on the demo.

The 'auto' side margins on div.rigid will center the demo in 'standards compliant' browsers, but IE5.x/win does not obey these, so I have employed a 'text-align' hack to force that browser to center the demo. That same browser has the infamous 'box model problem', so the decorative side borders I placed on the demo would have caused a col-wrap (in IE5.x/win), were in not for the box model hack I used to prevent this.
(see the source for details on these hacks)

Are you getting as tired of 'that browser' as I am? It's the new 'Nav4', people.

Speaking of Nav4...

I suppose some will wonder if these 3-col methods will work in Nav4. The answer is 'more or less'. I have prepared a separate demo that does work in Nav4, as long as one doesn't expect too much.

I tried hard to make Nav4 work acceptably, but failed. A percentage sized layout will indeed 'work', but there are puzzling horizontal openings between the cols that appear at semi-random screen sizes. I believe Nav4 can only render the 'width' of percentage based floats in large 'steps'. That is, when the screen size is incrementally reduced, the gap(s) get smaller and smaller, 'til contact triggers a jump to the next smaller box size. More than one box is involved, so both inter-col areas can show gaps.

Naturally, attempting to size cols under these conditions is dicey at best. The cols are indeed in the correct order, and at roughly the same height, but the 'gaps' can only be eliminated at a selected screen size, or two if you're lucky.

A pixel sized layout has its own re-sizing problems, because when the screen is reduced, a scrollbar is not created; rather it's the third col that is 'squeezed' until it's down to one 'word' wide, when finally a horizontal scrollbar makes its appearance, a little too late.

If you must cater to Nav4, use the percentage method, and live with the variable gaps. Remember that the values that work in Nav4 will not work in other browsers, and will require hacking to achieve similar results.

What This Method Cannot Do

Many site designers would like to have three source ordered columns, and have the two side cols be of a fixed width while allowing the center col to fluidly fill the remaining screen space. Sadly, this just isn't possible.

The problem is that the center col must be a float (as well as the float wrapper), and floats must have a stated "width". The only length unit that is not fixed is "percentage", but if the center col is given a certain percentage width, then whatever space is left in that float's container must also be a percentage. It's currently impossible to mix two boxes with percentage and fixed widths in a single container. At least it's not if you need to fill the screen cleanly at all resolutions.

Perhaps someday it will be possible to give a float a width that is 100% of its container, minus a fixed amount, but today is not that day. If you must have these fixed side cols and fluid center col, you must stick with simple left and right floated side cols and live with the lack of an ordered source.

Research & Development

This demo has the honor of moving into obsolescence even before being released! (I'm so proud)
There are already some code variations on the ordered cols theme over at
Alex Robinson's Site. Now go over there, and try to poke holes in his layouts. Alex would want you to. (I'm on my way...)

If you write a cool new version of this layout concept (like Alex), and feel it should also be linked here, please contact me, okay? :-)

Conclusion

Please be aware that the layouts detailed on this page are fairly new, and have not been extensively tested with the many variations that could be applied within them. I'm quite certain that problems will arise when this happens, and would caution a 'go slow' approach. Start with the basic layout and add stuff to it, watching for bugs as you go.

Don't be suprised if you just take an existing 3-col layout, transfer it to this one, and get hit with a Mystery Bug.
(notice I didn't say ".. an IE Mystery Bug", 'cause I just can't be sure...)

The Ordered Cols method may be extended to more than three columns, by adding a second floated wrapper, and wrapping the 3rd and 4th cols inside it. So it would appear thus: [{1 2} {3 4}], or some similar arrangement. Have fun!

The source ordered three column techniques detailed here seem to be robust in standards compliant browsers, and as soon as lesser browsers are consigned to the porcelain bowl of history I expect these methods to be widely adopted across the Web.

Contributors

I know what you're thinking: "That Big John is sooo talented!" Well, that is true, but this page is largely the hard work (freely given) of many other people from the css-discuss list, including (but not limited to) Scott Sauyet, Douglas Livingstone, Victor Caston, Alex Robinson, Mike Papageorge, and Holly Bergevin. There's some wicked synergy in that e-list.

Special thanks to Holly Bergevin, who convinced me to take time to create this demo, collaborated mightly on it, and displays a talent for bug squashing, too.  : )


Holly 'n John   e-mail ©positioniseverything
Last updated: Febuary 5, 2003
Created Groundhog Day (Feb 2nd), 2003