Google analytics script

Latest jQuery CDN with code tiggling.

Saturday, 30 July 2011

Use CSS floats to flow data in columns rather than rows with jQuery .transpose() plugin

I know we have CSS3 multi-column layout that makes HTML content flow in columns dead simple but the problem is that only the most modern browsers (as of July 2011) support this CSS3 capability. As you might have guessed this means tough luck for Internet Explorer users. Microsoft decided that CSS3 column layout is not something developers or better web designers would need so IE still doesn't support it. Not even in version 9 that is.

Even though CSS3 multi-column support got supported recently we have been displaying data in pseudo columns for some time. We either displayed tables when we had tabular data or used CSS floats or CSS inline-blocks when displaying lists and we didn't want the list to be long and narrow which makes it hard to use. The nice thing about floating is that elements take as much horizontal space as they can inside container and when individual items are set a fixed width this means that they will display in column-like layout. The problem is though that floated items run in rows meaning that when you have alphabetic text (or numbers) list items they won't flow in columns as we're used to ie. in phonebooks. No. Items flow in rows. This makes these kind of lists hard to read and search through. But I have a solution for you. jQuery plugin that re-arranges your items into columns to improve their usability.

If you need to get the code, head over to GitHub project where you'll find debug version of the plugin as well as a minified one that should be used in production environment. There's also a demo file along with them so you can test the plugin 'till your browser or computer drops dead.

The problem dissected

Anyway. Floats work like this: you set float: left; on your items (most likely using a CSS class to avoid repeating code), give them a fixed width and off you go. Let's display US States in this manner here. This is how they're listed using default left floating:

Alabama
Alaska
Arizona
Arkansas
California
Colorado
Connecticut
Delaware
Florida
Georgia
Hawaii
Idaho
Illinois
Indiana
Iowa
Kansas
Kentucky
Louisiana
Maine
Maryland
Massachusetts
Michigan
Minnesota
Mississippi
Missouri
Montana
Nebraska
Nevada
New Hampshire
New Jersey
New Mexico
New York
North Carolina
North Dakota
Ohio
Oklahoma
Oregon
Pennsylvania
Rhode Island
South Carolina
South Dakota
Tennessee
Texas
Utah
Vermont
Virginia
Washington
Washington DC
West Virginia
Wisconsin
Wyoming

As you may see they are displayed alphabetically but in rows, so Alaska is to the right of Alabama where it should be below it. Well you may think that this is not that much important but let's try and find Nebraska. You probably had to look in multiple columns because you can't know in which column you can expect it. And since columns give our brains signal to visually skip in vertical line it makes it hard to horizontally define where states starting with "N" are. If you look closely you can see they're all approximately in the same rows.

This problem is even more emphasized when list is longer or has more columns. Then it becomes rather hard to handle especially when users are required to search for individual items within this list (ie. to select it or more of them). This becomes a serious usability issue.

Solution is item transposition

As this blog post suggests in its title the purpose here is to give you a jQuery plugin that can reorder floated lists so that items seem to be flowing in columns rather than rows. This reordering is also known as transposition. There's also an Office Excel formula called Transpose that does the very same thing. It flips a table of data by exchanging rows for columns and vice versa.

This plugin of mine doesn't exactly transpose items because in our case of US states we don't want to end up with 13 columns of states each having 4 rows. No we basically just transpose items within this column layout and keep layout untouched. So this is not exactly transposition as defined in mathematics with their matrices but it does a similar thing with individual items.

Why are we doing this on the client? Why can't we order items on the server so we don't display them alphabetically but rather in a special order so they will get displayed as if they're displayed alphabetically in columns? The problem is client browser rendering. Floats may get rendered in 3 columns in some browsers but in others in 4. If your content doesn't have a predefined width (as this blog does) number of columns may vary greatly depending on user browser window size. The fact is you don't solve client issues on the server, but rather on the client.

Let's display our states again:

Alabama
Alaska
Arizona
Arkansas
California
Colorado
Connecticut
Delaware
Florida
Georgia
Hawaii
Idaho
Illinois
Indiana
Iowa
Kansas
Kentucky
Louisiana
Maine
Maryland
Massachusetts
Michigan
Minnesota
Mississippi
Missouri
Montana
Nebraska
Nevada
New Hampshire
New Jersey
New Mexico
New York
North Carolina
North Dakota
Ohio
Oklahoma
Oregon
Pennsylvania
Rhode Island
South Carolina
South Dakota
Tennessee
Texas
Utah
Vermont
Virginia
Washington
Washington DC
West Virginia
Wisconsin
Wyoming

As you can see they're still displayed in the wrong order. But let's click transpose states now and try to find Nebraska again.

You may have noticed that your eyes started searching for it in columns again (because brains get this strong vertical visual clue) but this time items really are ordered in columns so this list becomes usable to our brains. Plugin only allows one transposition within the same container because otherwise we'd end up with completely unordered list of items.

So where's the plugin code then? On GitHub of course!

As this plugin is usable to the general public I've published it on GitHub (with referenced open source licensing) where it will be much easier to maintain. It also offers the possibility to have two files there: a development version and a minified version that's less than 1k in size and is intended for production environment. Please test it and provide feedback either here on this blog or on GitHub if you're registered there. I will keep the plugin updated if some bugs arise.

So hurry and get your fix on GitHub now.

What else does it do?

Plugin is smart enough and check whether you've provided a set of elements that belong to different containers. It's or course natural that each group of items should be transposed individually. Hence plugin works this way as well. It filters out individual sets of items and transposes them per filtered groups. This has two benefits:

  1. You don't have to call .transpose() on each group of items you'd like to transpose which means that less code has to be written.
  2. If you do make a mistake everything will still stay in predictable order.

As of version 1.0 this plugin doesn't provide any additional options, but it may in the future so come back and check it out again next time or if you're a member of GitHub you can follow the project and be notified when anything new comes along. Happy coding fellow developers.

10 comments:

  1. Works great but for some reason I can't seem to make it work on a list that is initially hidden. Any suggestions?

    ReplyDelete
    Replies
    1. You're obviously hiding your list using display: none. This will make it impossible to transpose because plugin can't calculate how many items are there per row.

      Workaround: You can always use visibility CSS setting which invisibly renders elements and if your list is part of the document flow (so it would still take visible empty splace) you can also set position: absolute and then revert it back to inherit after you've done the transposition.

      I hope this helps. Let me know if it does.

      Delete
  2. Nice concise work Robert!

    ReplyDelete
  3. Works great when the list is first displayed but when I resize the window which in turn resizes my list e.g. from 3 cols to 2 then they are unordered. I've tried detecting window resize and calling transpose again but that doesn't work. It needs a page refresh. Any way of achieving this?

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete
  5. Not working google chrome :(. plz fix it.

    ReplyDelete
  6. Very Nice Plugin. Works perfectly great in in all major browser except google chrome. if you can fix it then it would be great.

    ReplyDelete
    Replies
    1. Used to work in Chrome as well. Will have a look.

      Delete
  7. Another user commented that this will cause the list to go back out of order once the window is re-sized, when testing the plugin I noticed we can only fire it once at a list and cant re-sort that list based on a specified event(a window resize etc...).

    I'm going to go ahead and try and work on this over the weekend and maybe I can submit a fixed version to your github.

    ReplyDelete