The standard formatting for an HTML list is
for the list items to be stacked, flush left, indented from the
left margin, and preceded by a bullet or number. That works fine
for a typical list, in which each item consists of a sentence or
two of text. However, when the list items are very short (e.g., a
long list of items composed of a word or two each), you end up with
a tall, narrow column of text on the left side of your Web page
with a big empty space to the right. That’s when many Web designers
start looking for ways to break a long list into multiple
side-by-side columns instead of a single long column.

Eventually, CSS 3 will provide the tools to
define snaking text columns, but it will be years before browsers
will broadly support the CSS 3 specifications. Until then, Web
builders will need to rely on other techniques for creating
multicolumn lists. So, let’s look at some of the techniques that
work with today’s browsers.

Technique 1: Floating list items

One of the simpler ways to create a multicolumn
list is to define a fixed width for the <li> tag and float
the list elements across the page. You can define the number of
columns by setting the width of the <ul> or <ol> tag.
The technique, shown in Figure
A
, is simple and effective, provided you can live with a
couple of peculiarities.

The first peculiarity is the order of the list
items. They flow from left to right across the page, and then drop
down to fill in the next row. That’s counter to the normal tendency
to read down a column before moving to the top of the next column.
The way the list items are arranged on the page may not be
significant if the list order is completely arbitrary to begin
with, but many lists have some intrinsic order, even if it’s just
an alphabetical arrangement.

Floated list items also suffer from
browser-compatibility issues, and, of course, the problem browser
is Internet Explorer. For some reason, IE omits the bullets in
unordered lists and numbers every item in ordered lists with the
number one. Fortunately, this isn’t a problem for the many lists
that don’t need bullets or numbers. If it’s a problem for your
list, you can use one of the other techniques.

One of the advantages of the floated list item
technique is that it requires no change to the normal list markup.
For example, here’s the XHTML markup for the list shown in Figure A:

<ul>
  <li>Item one</li>
  <li>Item two</li>
  <li>Item three</li>
  <li>Item four</li>
  <li>Item five</li>
  <li>Item six</li>
  <li>Item seven</li>
  <li>Item eight</li>
  <li>Item nine</li>
  <li>Item ten</li>
  <li>Item eleven</li>
  <li>Item twelve</li>
</ul>

And here’s the CSS that turns that standard
list into multiple columns:

ul {
    width: 700px;
    list-style-type:none;
}
li {
    width:180px;
    margin:15px 0 0 0;
    padding:0 10px 0 0;
    line-height:15px;
    float:left;
}

Note that the width:700px rule in the ul style sets the maximum
width of the list to a little more than three times the width of
the individual list elements (as set by the width:180px and margin:15px 0 0 0 rules in
the li style), thus
creating three columns. The list-style-type:none rule in
the ul style removes the
bullets from the list items in other browsers so the list matches
the way it appears in IE. The key to this technique is the float:left rule in the li style. That’s what causes
the list items to be arranged in rows across the browser window
until they fill the width of the parent element (the <ul>
tag).

Technique 2: Manipulating margins

Another way to create a multicolumn list effect
is to use margin settings to push some list items to the right and
up to form the second and third columns as shown in Figure
B
. This technique has the advantage of keeping the list
items arranged in columns that read down before going to the top of
the next column. However, the technique requires quite a bit of
extra markup and CSS code to make it work. Also, although there’s
no problem with disappearing bullets, this technique has its own
browser compatibility issue with IE. In this case, the problem is
that IE doesn’t want to recognize hyperlinks in the first two
columns. Fortunately, there’s an easy, one-line hack that fixes the
problem.

Here’s the XHTML markup for the multicolumn
list example in Figure B. Note the classes used to define the three
columns, and the additional classes applied to the first list item
in the second and third columns.

<ul>
  <li class=”licol-1″>Item one</li>
  <li class=”licol-1″>Item two</li>
  <li class=”licol-1″>Item three</li>
  <li class=”licol-1″>Item four</li>
  <li class=”licol-2 licol-first”>Item
five</li>
  <li class=”licol-2″>Item six</li>
  <li class=”licol-2″>Item seven</li>
  <li class=”licol-2″>Item eight</li>
  <li class=”licol-3 licol-first”>Item
nine</li>
  <li class=”licol-3″>Item ten</li>
  <li class=”licol-3″>Item eleven</li>
  <li class=”licol-3″>Item twelve</li>
</ul>

The CSS styles for this technique aren’t
terribly complicated, but the code does start getting longer as it
defines all of those added classes.

li {
    width:180px;
    margin:15px 0 0 0;
    padding:0 10px 0 0;
    line-height:15px;
    position:relative; /* IE needs this in
order to recognize links in all
 columns */
}
.licol-1 {
    margin-left:25px;
}
.licol-2 {
    margin-left:250px;
}    
.licol-3 {
    margin-left:475px;
}
.licol-first {
    margin-top:-105px;
}

The li style starts by setting
the column width (width:180px), and also the
margin (margin:15px 0 0
0
), padding (padding:0
10px 0 0
), and line height (line-height:15px). The other
techniques include similar rules, but it’s especially important in
this technique because we need to know the exact vertical space
occupied by each column. The position:relative rule is
included to fix IE’s problem with hyperlinks being ignored in any
column except the last one on the right. Why that particular rule
fixes the problem makes about as much sense as the problem itself,
but it works.

The .licol-1, .licol-2, and .licol-3 styles set the left
margins for the respective columns. The trick to this technique is
in the .licol-first
style. That’s what moves the second and third columns up so that
they’re aligned side-by-side across the page instead of being a
series of stair steps down the page. Specifying a negative top
margin (margin-top:-105px) moves the
column up above its natural starting place immediately below the
previous list item. To get the top of the column to align with the
previous column, you need to calculate the height of the previous
column. In this case, there are four lines and three spaces, each
measuring 15px, so the vertical offset is 105px (7 x 15 = 105).
Because both the first and second columns of this example are the
same height, I was able to use one class to define the vertical
offset for both the second and third columns. If those columns were
different heights, you’d need separate styles to set the vertical
offset for each column.

The margin manipulation technique works for
simple multicolumn lists, but it can be cumbersome to build (and
even more cumbersome to maintain) for lists that are even slightly
complicated or require editing and updating.

Technique 3: Divvying up with divs

The third multicolumn list technique takes a
brute force approach to the challenge—it breaks a long list into
shorter segments, makes each one a separate list, and places each
list in a div. Then you can arrange the divs into columns by
defining their widths and floating them across the page. It’s not
the most elegant approach, but as Figure
C
shows, it keeps list items in their normal order and can
easily accommodate fluctuations in column height.

Here’s the XHTML markup for the multicolumn
list example in Figure C.

<div class=”licol”>
  <ol>
    <li>Let me not to the marriage of
true minds</li>
    <li>Admit impediments; love is not
love</li>
    <li>Which alters when it alteration
finds</li>
    <li>Or bends with the remover to
remove</li>
  </ol>
</div>
<div class=”licol”>
  <ol start=”5″>
    <li>Oh, no, it is an ever fixed
mark</li>
    <li>That looks on tempests and is
never shaken;</li>
    <li>It is the star to every
wand’ring bark</li>
    <li>Whose worth’s unknown, although
his height be taken</li>
  </ol>
</div>
<div class=”licol”>
  <ol start=”9″>
    <li>Love’s not Time’s fool, though
rosy lips and cheeks</li>
    <li>Within his bending sickle’s
compass come;</li>
    <li>Love alters not with his brief
hours and weeks</li>
    <li>But bears it out even to the
edge of Doom</li>
  </ol>
</div>

Although the markup for this technique is more
involved, the CSS styles are quite simple:

li {
    margin:15px 0 0 0;
    padding:0 10px 0 0;
    line-height:15px;
}
.licol {
    float: left;
    width: 200px;
}

Creating list columns by placing three separate
lists within three separate divs may look like overkill. You might
be tempted to stick with one long list in the markup and break it
into three columns with <div> tags placed within the list.
Although that will produce the expected result in most current
browsers, it won’t validate due to improper nesting, and the
invalid code may not work in future browsers. Another option is to
omit the divs and apply the .licol class directly to the three
<ol> tags. Unfortunately, that creates problems with
disappearing bullets and numbers in IE, which leaves the
list-within-div approach as the most predictable cross-browser
solution.

The CSS styles for this technique are the
simplest of the lot. All you really need is the .licol style to set the
width of the columns (width:200px) and float the
divs (float: left). In
this case, the li style
is just for consistency with the other techniques—it doesn’t
affect the way the technique works.