Stupid css tricks: line breaks in lists

Periodically I encounter some problem with html and css layouts that could be solved by adding a few extra presentational tags to the html source (like <br/> or text bullets in the case I'm about to describe), but there's no easy way to do it in CSS.  I almost always end up caving and doing it that way, but I like flailing around and trying new things first before giving up.  I feel like sharing the most recent example because I'm almost proud of it, and in some circumstances it might actually be the right thing to do.

What I have is a list of links for a blog.  This is an excellent candidate for an unordered list, except that I want them presented like so:

one - two - three

four - five - six

seven - eight

The trick here is getting the dashes so they show up only in the middle of each line.  But there's no easy way to tell where the natural line breaks are, so I cant just have the first <li> per line not have a dash in front of it.  That means I'm probably going to need to insert some line breaks so I know which ones are at the beginning of a line, but I'd still rather not do it in the html.

I ended up with this:

.blogroll { text-align: center; }
.blogroll li { display: inline; padding: 0 6px; }
.blogroll li + li:before { content: '-'; position: relative; left: -8px; }
.blogroll li:nth-child(3n+1):before { content: '\a'; position: static; white-space: pre; }

The first two lines just make the elements centered, inline, and separated a bit. The third line puts a dash before all<li> elements that come after another <li> element--effectively everything but the very first in the list.  The fourth one is the magic: it uses a new css selector nth-child to select the element after every third element (that's the "3n+1" bit) and replaces the dash with a newline character (that's the "\a" bit).  Normally newline characters are just converted to spaces, but setting the white-space to "pre" makes the line actually wrap there.

It almost works!  Unfortunately, there is a case it doesn't handle well.  If one of the items is too long, the lines will wrap before the third item and you end up with this:

one - two - three

four - reallyreallylong

- six

seven - eight

Oh well.  I guess I'll be putting those line breaks in by hand after all.  But if you don't have to worry about that, it might actually be a good technique!

Comments