« In with the New | Main | Wrapping a Div around Floats in HTML »

DIV Column Layouts in Any Order (Almost)

This is a complete digression for a blog on Django and Flex, I want to talk about some HTML I've been working on. My project is some technology to automatically generate and design web-pages, through my R&D company. There are two things I've discovered, so look out for a further post on the other.

This post is about how to create DIV column layouts where the columns are given in the HTML in any order, but are displayed correctly when rendered, allowing you to have SEO-friendly content first in the HTML page, even if it appears in the middle of your column layout.

To lay out my pages I needed a mechanism for creating columnal layouts without tables, so I've used the common floating DIV trick:

<div>
  <div style="float: left; width: 180px">
    Column One Content
  </div>
  <div style="float: left; width: 500px">
    Column Two Content
  </div>
  <div style="float: left; width: 280px">
    Column Three Content
  </div>
</div>

(note that I'm doing these examples with fixed column widths in pixels. I normally prefer fixed-width in ems, but you could also use percentages for resizing. This approach doesn't allow you have some flexible size columns and others fixed width, however)

But column one (in many cases a navigation toolset) comes first. For SEO optimisation I want content to come first. This may be in a different column. In fact, I'd like to be able to put my column content into the HTML in any order, but have the layout work.

It turns out this is possible in most cases, by wrapping sets of columns in further div tags, and floating them as a whole. So, for example, if in a three column layout we want the middle column first in the HTML, then the right column, then the left, we'd do:

<div>
  <div style="float: right; width: 780px">
    <div style="float: left; width: 500px">
      Column Two Content
    </div>
    <div style="float: left; width: 280px">
      Column Three Content
    </div>
  </div>
  <div style="float: right; width: 180px">
    Column One Content
  </div>
</div>

In other words we group columns 2 and 3 together and right float the group, then add the leftmost column, also floating right. The logic is that a set of columns can be either left-to-right ordered (if each is floated left) or right-to-left ordered (if each is floated right). So with a combination of groups you can get most layouts.

Only most? Well yes. I wrote some software to calculate all possible permutations. For two columns you don't need to group at all, for three you can get all possible permutations this way. For four columns there are two permutations that are impossible. That number increases to 30 (out of 120) for five and by six, most (394 out of 720) orders are impossible. I would hazard a guess, however, that six columns isn't near the top of the average designer's toolbox.

So here's the meat. These tables show the order of columns on the left, and an abbreviated layout code on the right. The example from above is

2, 3, 1: (←2, ←3)→, 1→

We want the column two to appear first, then column three, then column one (hence 2,3,1 on the left). The code on the right tells us we need to put columns two and three, each floated left, into a div that is floated right, followed by column one on its own also floated right: exactly what we had in the HTML code above.

2 columns

1, 2: ←1, ←2
2, 1: 2→, 1→

2 out of 2 are possible

3 columns

1, 2, 3: ←1, ←2, ←3
2, 1, 3: ←(2→, 1→), ←3
2, 3, 1: (←2, ←3)→, 1→
1, 3, 2: ←1, ←(3→, 2→)
3, 1, 2: 3→, (←1, ←2)→
3, 2, 1: 3→, 2→, 1→

6 out of 6 are possible

4 columns

1, 2, 3, 4: ←1, ←2, ←3, ←4
2, 1, 3, 4: ←(2→, 1→), ←3, ←4
2, 3, 1, 4: ←((←2, ←3)→, 1→), ←4
2, 3, 4, 1: (←2, ←3, ←4)→, 1→
1, 3, 2, 4: ←1, ←(←(3→, 2→), ←4)
3, 1, 2, 4: ←(3→, (←1, ←2)→), ←4
3, 2, 1, 4: ←(3→, 2→, 1→), ←4
3, 2, 4, 1: (←(3→, 2→), ←4)→, 1→
1, 3, 4, 2: ←1, ←((←3, ←4)→, 2→)
3, 1, 4, 2: Impossible
3, 4, 1, 2: (←3, ←4)→, (←1, ←2)→
3, 4, 2, 1: (←3, ←4)→, 2→, 1→
1, 2, 4, 3: ←1, ←2, ←(4→, 3→)
2, 1, 4, 3: ←(2→, 1→), ←(4→, 3→)
2, 4, 1, 3: Impossible
2, 4, 3, 1: (←2, ←(4→, 3→))→, 1→
1, 4, 2, 3: ←1, ←(4→, (←2, ←3)→)
4, 1, 2, 3: 4→, (←1, ←2, ←3)→
4, 2, 1, 3: 4→, (←(2→, 1→), ←3)→
4, 2, 3, 1: (4→, (←2, ←3)→)→, 1→
1, 4, 3, 2: ←1, ←(4→, 3→, 2→)
4, 1, 3, 2: 4→, (←1, ←(3→, 2→))→
4, 3, 1, 2: 4→, 3→, (←1, ←2)→
4, 3, 2, 1: 4→, 3→, 2→, 1→

22 out of 24 are possible

If you want the tables for higher numbers of columns let me know, and I'll email you them.

TrackBack

TrackBack URL for this entry:
http://www.icosagon.com/mt/mt/mt-tb.cgi/166

Comments

Some of your examples use to many nested divs. You can do 1,3,2 by: 1-float-left, 2-float-right, 3-float-either without the nested div.

Thanks for pointing this out - you're right. The code I wrote to automatically generate the chart doesn't take into account mixing float directions within one div. Adding that in is quite tough - but it would be worth doing, so I may have a go and update this page. It would be relatively trivial to do it for small numbers by hand, but I like the programming challenge.

Interestingly, It doesn't make possible any of the cases I've marked as impossible.

"I'd like to be able to put my column content into the HTML in any order, but have the layout work."

Isn't it possible to place the DIVs in any order, for SEO, and still have the required layout using CSS class selectors?

Yeah, you can do this: specifying the position of each give in absolute positioning. The problem is that I couldn't find a way to then surround the content with a div, so I can do my background, any height column trick. Using combinations of floats (which is more common) gives you that option.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)