CSS Swag: Multi-Column Lists

by Paul Novitski

59 Reader Comments

Back to the Article
  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. 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.
  13. 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.
  14. 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.
  15. 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.
  16. 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.
  17. 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.
  18. 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.
  19. 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.