CSS Swag: Multi-Column Lists

by Paul Novitski

59 Reader Comments

Back to the Article
  1. Some of these methods will get very messy if the text of some of the list items is long enough to wrap lines. Just something to lookout for before committing to a method.

    Copy & paste the code below to embed this comment.
  2. I posted about this problem a while ago on my website. It may be relevant to study the comments I got when I asked how to do a split list suitable for Netscape 4:


    Copy & paste the code below to embed this comment.
  3. Rather than eliminating all whitespace inside a list element I prefer to just set the <li> tag to display: inline;

    This may not be suitable in all instances (if you just want a plain list say). However as this list is to be styled further with floats and possibly other display settings (on the links in each li for example) I think it is a more elegant solution.

    Copy & paste the code below to embed this comment.
  4. Could we not maintain semantic integrity, simple CSS, AND get our nice, beautiful, multi-column layout by using Javascript to convert lists into a multi-column variant?

    In this way, everything degrades to a simple list; but for virtually all users, you get your multi-column list with none of the caveats mentioned.

    Copy & paste the code below to embed this comment.
  5. It seems a little funny to use a class to uniquely identify an item.

    Classes tag an item as being part of a group. If the aim is to uniquely identify something on a page, then assigning an ID to the item is probably a better route to go.

    Copy & paste the code below to embed this comment.
  6. David, one issue with declaring list items as inline is that inline elements can’t be assigned dimension in the same way a block element can, limiting their usefulness in creating navigation menus & the like.

    Copy & paste the code below to embed this comment.
  7. Boy, is that ever hairy markup… and absolutely positioning everything?

    I’d rather use multiple lists than have to break DRY like this. I mean, what a disaster when you have to add a nav item in your markup and then track down and fiddle with all these numbers in your stylesheet.

    After all, as stated in the article, it’s like three lines of PHP and an associative array to have complete control. Alternatively, if the markup is sacred, have a tiny server-generated stylesheet that auto-calculates the menu item positions.

    Copy & paste the code below to embed this comment.
  8. Jason, you’re right about the graceful degradability of client-side scripting solutions; while I did mention scripting in passing, I was focusing on CSS solutions in this article. While I use JavaScript myself, it has its own caveats: similarly to CSS it’s not universally supported, neither by makes & models of browser nor by all users.  Further, I find that most javscript solutions that purport to leave the markup simple actually heavily augment the DOM when they run.  To what extent does it matter whether I complicate the XHTML and CSS by hand or write a script to do it for me if the resulting DOM will be the same?

    Copy & paste the code below to embed this comment.
  9. Drew, the reason I identified list items using class instead of id was to facilitate more than one list on the same page; ids work just fine if that isn’t a concern.

    Copy & paste the code below to embed this comment.
  10. Method 4 would be the useful when you are generating content using sever side scripting (i.e. PHP), you could have a simple little function that takes a list (i.e. from an array) and splits it into N numbers of columns by assigning class=“columnN” and class=“columnN reset” through a for loop. This removes the need to ‘tweak’ the source each time there’s an item added or removed from the list.

    Only useful for generated content, and probably only in certain situations at that, but once implemented it looks after itself, as long as you can live with presentation vs semantics use of CSS class names.

    Interesting article Paul, thanks for the different ideas.

    Copy & paste the code below to embed this comment.
  11. Like most other readers of articles on this site, I’m always interested in experimentation and exploration of issues related to the implementation of proper standards and markup. And I absolutely enjoyed the exploration of so many different options presented here.

    However, with each new example this article seemed to get farther and farther away from our true “holy grail” of generating pages that utilize the simplest, most compatible markup.

    If all the content were contained within the markup (i.e. not supplied via a CMS), my question is why not use CSS to simply style these lists manually, and avoid using OL & LI tags entirely?

    Certainly the auto-numbering of OL tags is a strong tool and like other aware developers I too long to have numbered columns that can “swagger.” However, if I’m going to build custom code on a list-by-list basis, it seems to make a lot more sense—and is ultimately much more compatible—to do so within the XHTML markup than CSS.

    Copy & paste the code below to embed this comment.
  12. Actually, Konqueror does just fine with the example in Method #3.  I would assume Safari does as well.  And Firefox handles generated content as well—it’s the counters and counter increments that it doesn’t seem to support.  Firefox 1.5 is “supposed to”:http://developer.mozilla.org/en/docs/What’s_New_in_Deer_Park_Alpha handle counters, but when I load the example they all show up as “1. whatever.”  It looks like it’s using the counter, but not incrementing it.

    Come to think of it, IE is pretty much the only major browser that doesn’t support the :before pseudo-element.  Unfortunately, last I looked it wasn’t on the “list of additions for IE7”:http://blogs.msdn.com/ie/archive/2005/07/29/445242.aspx

    Copy & paste the code below to embed this comment.
  13. I found a description of what’s different about Firefox 1.5’s implementation of counter-increment.  (The release notes just say it matches an upcoming draft of CSS 2.1 rather than the current one, without saying what’s changed.)  Apparently you need to put counter-increment “in the tag’s style”:http://www.davidflanagan.com/blog/2005_08.html#000075 instead of in the :before pseudoelement’s style.  This still works fine in Opera.

    There is one further step to getting it to work as expected in Firefox, since “scope is an issue”:https://bugzilla.mozilla.org/show_bug.cgi?id=3247#c113 in the new way of handling counters.  Ending the LI’s parent—the OL—ends the counter’s scope unless you define it somewhere further up the tree, and you get each column starting over at 1.  If you apply “counter-reset: item” to div.outerwrap, it sets the scope so that the counter doesn’t reset on each OL, and you get continuous numbering in both Opera and Firefox 1.5.

    Copy & paste the code below to embed this comment.
  14. I can confirm “Kelson Vibber’s assumption”:http://www.alistapart.com:80/comments/multicolumnlists?page=2#12 that Safari handles at least some generated content (such as plain text).  It cannot handle the counters and I’m sure there are a few other things in the ways of generated content it doesn’t handle.  So it’s finicky at best.

    Copy & paste the code below to embed this comment.
  15. Nice in-depth analysis. However, there are some errors in one of your examples. Under “Wrapping a single list with CSS” you have a bunch of orphaned closing anchor tags:

      ><li class=“aloe”>Aloe</a></li
      ><li class=“berg”>Bergamot</a></li
      ><li class=“cale”>Calendula</a></li
      ><li class=“oreg”>Oregano</a></li
      ><li class=“penn”>Pennyroyal</a></li

    Otherwise, great article!

    Copy & paste the code below to embed this comment.
  16. I recently had to do something similar. I wanted to keep the HTML simple so that the list was easily editable. I relied on a combination of JavaScript and CSS. Sometimes heavy DOM augmentation is necessary to get what you want, but I don’t think it’s necessary for this particular trick.

    My method is similar to #4 in your article, but did a lot of the heavy lifting in JS. One of the benefits is that the JS will determine the height of the list and dynamically create two columns (currently it’s limited to two columns).

    I will note that one problem I encountered that I have not yet had time to fix is the list element marker (number or bullet). IE has a particularly nasty problem where the marker for multi-line list elements shows up next to the last line instead of the first (something to do with “hasLayout” I suppose). Becuase of this the CSS removes the markers, which luckily I did not need.

    The code still requires quite a bit of clean-up, I still have some improvements to make, there are some problems that I have yet to figure out, and the documentation is pretty much non-existent. Anyone interested can find a demo page at <http://www.eclecticgeek.com/mcl.asp>.

    Copy & paste the code below to embed this comment.
  17. Any easy way to force IE to render without list-items without whitespace is to just define a line-height. I use:

    li {
    line-height: 150%;

    This styles the spacing to match my paragraphs, and seems to get IE to play nice with the other browsers. It sure beats having to do line-breaks in your HTML. ;)

    Copy & paste the code below to embed this comment.
  18. Tweak this so that instead of having a unique class (.name) for each value, just have a class that indicates what column it should sort into…

    and so on, and then just toggle through those when adding to your list.  You could automate this even further by running this through a server for the numbering party (and even for defining which class each <li> would be, as the author suggests.

    Let me know if this is tomfoolery.

    Copy & paste the code below to embed this comment.
  19. In the 2nd method, what is the purpose of using ‘display : block’ for the a element?

    Copy & paste the code below to embed this comment.
  20. As Avril Lavigne puts it, “Life is complicated”. So is this. Wouldn’t it be easier just to produce the list with the server-side script?

    Copy & paste the code below to embed this comment.
  21. Jason, the fundamental justification to use OL & UL structures for lists rather than Ps or DIVs is to give our documents semantic meaning.  When the content we present is meaningfully structured and not merely visually presented, our pages can more readily be interpreted by screen-readers, search engines, archiving engines, and other systems.

    Copy & paste the code below to embed this comment.
  22. Yasir, the purpose of making the normally inline A element a block is to enable us to assign it dimension.  When an anchor is a block, its clickable area is the full area of the block, whereas with inline anchors you can click only the hyperlinked text (or image) itself.

    You can see this effect in all of my live examples but especially “example 7”:http://alistapart.com/d/multicolumnlists/example7.html when you mouse over any portion of the rectangle that contains a list item.

    I like to do this to increase usability (the user doesn’t have to aim as precisely to activate a link) and attractiveness (in menus I often like to change the entire menu item block background on hover, not merely the link text itself).

    Copy & paste the code below to embed this comment.
  23. As “Kelson Vibber”:http://www.alistapart.com/comments/multicolumnlists?page=2#13 noted above, Firefox 1.5 beta can be made to work with Example 3. One just have to use the correct syntax. Another browser that supports this perfectly is little brother iCab 3.0. Safari (1.3 and 2.0) isn’t there yet.

    One problem to note with those various techniques (i.e. example 3): the second and third column are not perfectly aligned horizontally. Each column starts a few pixels higher or lower than the previous one. That is a consequence of the way browser round of values to the nearest pixel. On the Linux box, Firefox is correct, but Opera 8.5 was off by a few pixels. On my OS X box, the only browser to get it correctly is Firefox 1.5b.

    Copy & paste the code below to embed this comment.
  24. Thanks everyone who suggests that server- or client-side scripting is the solution to the multiple-column list problem.  Of course, any of the HTML & CSS solutions I’ve suggested in this article can be the underlying method used by a script.  No reason to do it by hand if you can program a robot to do it for you.

    Copy & paste the code below to embed this comment.
  25. Great article.

    Thanks also for the insight into where the ‘jolly swagman’ term comes from.

    Copy & paste the code below to embed this comment.
  26. Paul, there’s no argument from me when it comes to the importance of using OL/UL for the purposes of defining structure and the nature of the content. And don’t get me wrong—I love this article and I’m not trying to criticize you or its content in any way. I’m just looking to further the discussion on this subject, because I think you’ve brought up a significant conern.

    Hopefully I can make myself a bit more clear in my thoughts. :)

    Wrapping OLs across multiple columns is only a “holy grail” of the visual presentation aspects of XHTML/CSS. Yet this barely registers on the radar if we’re talking about presenting content to a screen reader.

    More importantly, as visually pleasing as multiple-column OL may be, the truth is that when presented on-screen, it tests miserably with reagards to usability (according to Edward Tufte and NN/G). This is not to say we should abandon our little Grail quest in this regard. On the contrary, I think this brings into question how important it is that certain content be presented in numerical order.

    While this article is presented from a technical/development standpoint, but isn’t the underlying message of ALA that development and design need to go hand in hand?

    We all love CSS and we all dream of heightened standards for both development and display. But our hopes for the future shouldn’t derail us from our primary responsibility as developers, and that is delivering universally readable content that maintains visual presentation.

    Copy & paste the code below to embed this comment.
  27. Another potential methodology is to not create the content in xhtml and stick to xml and use a xslt to style things. This allows a programatically neutral backend that can be reproduced on many levels. It also lends it self to transformation to other formatting that can be machine readable (RDF or otherwise). The negative of course is it does require scripting of some sort.

    A larger is issue to consider is that it brings forth whether or not semantic markup really matters. It is no where as close to being as usable or parseable as something like RDF or some other user created xml format. I am not saying of course that we should use xml documents to return to tons of tables and the like, but rather that our consideration for what is really “semantic” or proper should be considered in context. If an application drives this example, then it seems to be a moot point IMHO. Of course, if someone had to edit the pages (be it javascript, xhtml, css or otherwise) the strategies become much more important.

    Thanks for the interesting article.

    Copy & paste the code below to embed this comment.
  28. Thanks, Philippe, for reports of vertical alignment problems in Linus & OS X browsers.  In my early experiments with these techniques, I found that I had to set the line-height of list items to at least 1.2em in order for methods 5 & 6 to bring the first item of the next column up to the correct position.  I’m surprised that you report a similar problem with method 3, which is just three separate lists floated side-by-side.  I’ll look into it.

    Copy & paste the code below to embed this comment.
  29. Jason, it sounds as though you and I agree on this point: that wrapping lists into multiple columns is a matter of visual presentation and shouldn’t affect the semantic content of the markup.  That’s why I prefer methods that employ a single list manipulated by CSS over those that fragment a list into fragments positioned side by side (regardless of whether that fragmentation is performed manually or with script).

    I don’t see why a single list, wrapped visually into columns using CSS, would present problems for screen readers; can you elucidate?  Also I’d like to read the Edward Tufte article you cite; can you send me a link or bibliographic reference?

    Copy & paste the code below to embed this comment.
  30. Anissa, your suggestion for assigning class names to list items in markup in order to place items into columns sounds like what I described in “Method 4”:http://alistapart.com/articles/multicolumnlists/#method4—let me know if you had a different idea in mind.

    I don’t think it’s tomfoolery—it’s certainly workable and probably accessible to screen readers.  In my opinion it’s not an ideal solution since it codes the column placement in the content (HTML) rather than in the presentation (CSS), and I consider column-wrapping presentational.

    Copy & paste the code below to embed this comment.
  31. Very interesting article. Until the CSS 3 columns module gains wide support, I still prefer to use Method 1; I think I first saw it used on Eric Meyer’s site a year or two ago. I like the simplicity of the XHTML and CSS with no extra scripting. Actually I was surprised how quick and easy it is to recognize that the sequence is running horizontally and make the visual adjustment (using numeric markers might be a different story, though). I haven’t seen any of the usability data sited earlier that suggests problems with this approach (anyone willing to site a URL?). And I haven’t used this method with item markers, so that hasn’t been a problem for me either.

    Copy & paste the code below to embed this comment.
  32. Paul,
    Isn’t that just the funniest thing! I was so excited because I had actually thought of something to post on ALA.  I was too tired to realize it was your idea!  My head is hung in shame.

    Oh well, I shall console myself with the idea that at least I’m thinking like an ALAer.  Sigh.

    Copy & paste the code below to embed this comment.
  33. Paul (re: “28”:http://www.alistapart.com/comments/multicolumnlists?page=3#28 ). Actually, I was wrong in pointing to example 3; that one works correctly, as far as vertical alignment is concerned. The problem applies to those examples where you use negative top margins. When you first published your experiments on CSS-D, I did some testing on this. Never could them right across browser land, except when using either pixels for values, or using a line-height like ‘1’ or ‘2’. It is all due to way browsers attempt to slice pixels or rather the way they convert to screenpixels to render on screen when the line box does not have a round number of pixels for computed height.

    Copy & paste the code below to embed this comment.
  34. Great article but I’m only brave enough to use example 1 until css 3 is more widely supported. Nice work!

    Copy & paste the code below to embed this comment.
  35. Philippe (re “33”:http://alistapart.com/comments/multicolumnlists?page=4#33 ), can you tell me if you preserved my markup in its entirety—including the Strict DOCTYPE—when you tested examples in Mac browsers?  In my early experiments I found more default LI height variance between browsers with transitional or quirksmode rendering, confounding the vertical return calculation, which is one reason I ended up using Strict for this article.

    Copy & paste the code below to embed this comment.
  36. in example 6 you use different “unique” li classes to set up the margin’s. Is there really a need for unique handlers? I don’t get it. I guess in this case are 3 class-names enough.

    However, nice idea:)

    Copy & paste the code below to embed this comment.
  37. This may be incredibly pedantic but I thought an ‘ex’ was the measure of font height whereas an em is the measure of font width.

    But I found the article and subsequent comments very intersting and learnt something, so thanks.

    Copy & paste the code below to embed this comment.
  38. Thanks for a nice article, even though I don’t think I will be using the techniques. I prefer the (unobtrusive) javascript approach, with the ol or ul having a class “multiplelist” or whatever. The possible problem with multiple-line / different height-li’s seems to be catered for with a little help from the linked source in Brian Sweeney’s comment (#16).

    I can see a real potential use of multiple column lists in e.g. feature lists on product information pages.

    Copy & paste the code below to embed this comment.
  39. Eike (re: “36”:http://alistapart.com/comments/multicolumnlists?page=4#36 ), the purpose of assigning each list item a unique identifier within its list is to enable us to control column-wrapping entirely from the stylesheet.

    Both methods 5 & 6 use “this technique”:http://alistapart.com/articles/multicolumnlists/#method56

    If we use only one class name per column as in my “method 4”:http://alistapart.com/articles/multicolumnlists/#method4 then column-wrapping is controlled in large part from HTML.  In the interests of separating content from presentation, I prefer to control the wrap from CSS.

    Copy & paste the code below to embed this comment.
  40. Graham (re: “37”:http://alistapart.com/comments/multicolumnlists?page=4#37 ), you’re right that ex began life as a vertical measure (the x-height) and em as horizontal (the width of the lowercase m).  I tend to use them for both horizontal and vertical measurements, relying on the empirical formula 1em = 2ex which hasn’t failed me so far.

    Copy & paste the code below to embed this comment.
  41. Pär (re: “38”:http://alistapart.com/comments/multicolumnlists?page=4#38 ), thanks for your comments.  Even if you use javascript, your script needs to use some technique or other to wrap the list into columns.  If you use a technique other than one of the ones I describe here, please describe it for us to add to the heap.

    I don’t see javascript as an alternative to CSS, I see it as an alternative to hand-coding.  Whether or not you build a robot to do the dirty work, the work still has to be done by a specific technique.  Which do you choose?

    Copy & paste the code below to embed this comment.
  42. Re: #41
    Paul! I’m sorry, I was probably too quick with my comment. It’s true, I would still have to choose the way to do the actual column wrapping.

    My apologies if the rest of this post is not understandable due to my language. English isn’t my mother tongue. Please correct me or ask if anything seems unclear.

    The technique I choose would have to fulfill at least the following: it has to be degradable (“unobtrusive”), not use deprecated elements or attributes, and not force me to manually change the js, css or (x)html when adding or removing items to/from the list (except the manual change of adding or removing the items, of course). This removes method #2 from the list. I would use method #1 if I only used unordered lists (giving the ul a class of “multipleUnorderdList” and styling accordingly). If :before and content properties where widely supported, I would probably prefer method #3 (with the “sublists” created by js), and accept the extra list elements even though they might be unsemantic. My critique against method #5 and #6 is mainly because I would have to change the css (add classnames) on every change on the list (also, the use of classes on every element looks ugly! :).

    So I was thinking about method #4, and accept the “presentation intrusion on the content”. The columnN and reset classes would be set by js, making it easy to add or remove items. The ol would get a class “multipleOrderedList” or something similar for the js to “see” and work upon. I would still have to update the css when adding/removing items though, so I have to throw this solution away, too. This leaves me with nothing. If being forced by a customer to make a multicolumn ol, I would use something like method #6 and be angry about the solution not being dynamic. I would consider the problem unsolvable on my criterias until I saw “:before” and the “content-property” being widely supported, or read another ALA-article telling me how to do it. :)

    Still, this was a nice article. It got me thinking. Thanks. And if someone could point me to a solution that fulfills my criterias, thanks again!

    Copy & paste the code below to embed this comment.
  43. Uhu. The pseudoclass “:before” should be after the word saw in the long link in my previous post (#42). It was parsed as a textile command for “link”. I can’t see how I could miss that in the preview (which btw is a great thing!). I’m sorry.

    Copy & paste the code below to embed this comment.
  44. Pär (re: “42”:http://www.alistapart.com/comments/multicolumnlists?page=5#42 ), thanks for your thoughtful response (in excellent English!).

    JavaScript can automate all of these methods, even 5 & 6 if you let go of the separate stylesheet and accept some form of inline styling.

    Separating presentation in a stylesheet from content & structure in an HTML file is sensible when creating and maintaining web projects.  However, when a browser actually renders a page it necessarily mixes the two into a single DOM.  If you think of a javascript function as part of that rendering process, then the fact that it mixes CSS with HTML might be deemed forgiveable.

    To automate methods 4, 5, or 6, javascript can generate unique classes or ids and apply them to the list elements, then create CSS rules to arrange the list items into columns.  While javascript can’t literally modify a linked stylesheet file, it can modify the HTML document itself: insert inline styles into tags (ugh), insert a stylesheet into the HTML header (better), or modify the stylesheet in the DOM (best but more tricky and perhaps less cross-browser-friendly).

    Does it really matter if imposing classes on all the list items “looks ugly” when you the human will never see it?  Or doth the mere idea of doing so offend thine eye?

    While method 6 may be my favorite when coding by hand, if I were to assign javascript the task of formatting a list into columns, I think method 4 would require less scripting logic and less new material added to the DOM.

    Warm regards,

    Copy & paste the code below to embed this comment.
  45. Paul, thanks for your explanation. But I still don’t think any of the methods will work for me (please correct me if I’m wrong!). I can see what you mean with inline styles “on-the-fly” being acceptable for the sake of function, but I definitely wouldn’t like to mix css into either the html/content file or the js-file. That would make it too hard for a designer to change the styles. Restyling the site should, in my opinion, only be a matter of replacing one or a few css files for some other. I think the only way the script should be able to modify styles is by assigning class names and ids to the elements. Then it’s up to the designer to style for it.

    But you already know that. It’s me not understanding that we were looking at two different things. You wrote an article about different (experimental) ways to handle a problem. I was looking for the perfect solution, to use in a “write once, use anywhere”-script that could automate the process for me while being modular. Your article was great, I just have to accept that it didn’t provide the solution for me. It still was some interesting reading, and your answer to my comment and questions did clear a few things up. Thanks again!

    About individual classes on the list items: Yea, it’s true I would never have to see it if I assigned them from a script. It would offend me knowing they were there ;) but I could probably accept the usage. Still, the problem of having to update the css file manually matters more to me. As I surely have said to many times now. :)

    Looking forward to see your next article, hopefully on ALA.

    Regards, Pär.

    Copy & paste the code below to embed this comment.
  46. I read this article with pleasure & pain. I don’t get it why I should declare every item an own stylesheet just to get it in columns when I can do it simple with boxes?!
    Whatever, I guess the only possibility is to enact the Firefox 1.5 to every user until we got CSS3 as a standard ;)

    It would solve all problems with dynamic cols.

    (to be honest, every browser should integrate the column-css that we can create appropriately layouts!!)

    Copy & paste the code below to embed this comment.
  47. It would seem to me that this is a clear case where Tables should be used, at least for now.

    Yes, I’ve burnt the midnight oil creating entirely table free layouts using CSS2, but sometimes I can’t help wondering if I’m being too much of a purist, or rather, a prophet.

    In a world where we constantly innovate, we can often forget the simplicity of older innovations. This can result in brilliant ideas, but more often than not, turns into an overly complex “because I can” hack.

    The simplicity of multi-column layouts in standard HTML is so profoundly accessible, I see no point in trying to complicate the issue. It is, in essense, tabular data.

    The basic table tags are accessible by the vast majority of browsers and browsing devices and can be augmented with CSS2.

    Perhaps I’m missing the point entirely ?

    Although I will attempt these various CSS2 hacks, the humble HTML table remains to me, a vision of simplicity and elegance.

    Copy & paste the code below to embed this comment.
  48. The weekend the article was released I wrote a “script to automate the process”:http://arapehlivanian.com/2005/10/25/automated-multi-column-lists/. I then submitted it to ALA and waited for … well till now. So that’s why this comes so late. But for anyone who’s interested, it’s done.

    Copy & paste the code below to embed this comment.
  49. Gadget (re: “46”:http://alistapart.com/comments/multicolumnlists?page=5#46 ), I feel your pain.  Until everyone has CSS3-savvy browsers, however, we need solutions that come close or achieve our goals with today’s less-than-perfect tools.

    Copy & paste the code below to embed this comment.
  50. Mat (re: “47”:http://alistapart.com/comments/multicolumnlists?page=5#47 ),  tables might seem to be a solution at first, but let’s think it through.  For a three-column table, are you proposing a table with 3 columns and N rows?  Table cells are read across and then down, so if your table consisted of these nine cells:

    a | d | g

    b | e | h

    c | f | i

    …then your data sequence in the markup would be a,d,g,b,e,h,c,f,i.  Put that in your screen-reader and smoke it!  I think that’s sacrificing the integrity of the data in order to use table markup to get things to align properly.

    Another way to use a table for list-wrapping is to create one cell per column, so cell 1 would contain the first part of the list:




    cell 2 would contain the next part:



    and so on.  This splits the list into several sub-lists, which falls short of the ideal single semantic list, and uses the table purely for layout and not for its semantic structure.

    For me, another philosophical & practical disadvantage of using tables is that the markup controls the column-wrapping, which I consider presentational.

    Please let me know if I’m overlooking a table-based solution that preserves the sequence of the original list and uses the table as a semantically-meaningful structure and not merely a visual layout tool.

    Copy & paste the code below to embed this comment.
  51. If we’re talking which is more Semantically Pure™, I’m really not convinced that an attribute-encrusted nightmare of IDs beats a two-celled table.  Never mind, fer-God’s-sakes, unique classes.  Yeah, they’re attributes and not structure.  They also blow out the character count sonmething fierce.

    That said, I probably wouldn’t be keen on splitting an ordered list into columns of any sort anyway, what with it being a colossal pain in the bum to read.  If I do, however?  Ara’s JavaScript example looks pretty good right now.

    Copy & paste the code below to embed this comment.
  52. I used multi-column method for my list but i have a problem:
    my list have many rows and when i print it, it is printed only in one page and is not divided in multi-pages and i lost the last rows.

    Copy & paste the code below to embed this comment.
  53. using the column part: http://www.w3.org/TR/2001/WD-css3-multicol-20010118/

    ul li {
    column-count: 3;
    Column-gap: 1em;


    Copy & paste the code below to embed this comment.
  54. I’ve been messing with the CSS and HTML for awhile, but I can’t figure out how to get text to show up like:

    Text 1     Text 2
              Text 3
              Text 4

    and then repeat. Any help would be nice. (anormlguy007@yahoo.com)

    Copy & paste the code below to embed this comment.
  55. On my previous one, the spacing didn’t go through…

    Text 1 aligned left, then Text 2, 3, and 4 aligned right, with Text 1 and 2 on the same line.

    Copy & paste the code below to embed this comment.
  56. I used to design with HTML tables but then I found out the drawbacks of table and use of Divs instead. However my Float Left divs wrap underneath one another when they dont fit in the borwser’s size, for eg
    [first div] [second div] [third div]
    if you customize the size of browse to less 800 i get something like:
    [first div] /* second wraps */
    [second div] /* third wraps */
    [third div]

    Any idea as to How I need to solve this issue? Thanks.

    Copy & paste the code below to embed this comment.
  57. Nice post, one that I’ve only just stumbled upon….so I’ve read it, and im pretty sure that my navigation isn’t going to change, so I’ve opted for Method 4.

    And it works…that is until I changed it to use a bulleted list and instead of using a bullet image, I used a background image. Adding the code below to the “ul li” class works for all but the top two items in each subsequent list after the first.  Removing the “position:relative” ie/hack solves it, but then the ol’ link problem reoccurs..

    background-image: url(../images/bullet.gif);
    background-repeat: no-repeat;
    background-position: 10px;

    Any ideas how I can get round this?

    Copy & paste the code below to embed this comment.
  58. I used method 6 for a 2-column list but noticed that in IE the second column inherited the background from the parent element.  It has something to do with the negative margins as using a positive or zero margin resulted in no background for the second column.  The easiest way around this bug is to set the background to “none” for all li elements.

    Copy & paste the code below to embed this comment.
  59. You can create multicolumn lists with my “List Splitter”:http://www.polisource.com/PublicMisc/List-Splitter.html application. Cool animation too.

    Copy & paste the code below to embed this comment.