Sexy HTML List Tricks
Behold the ubiquitous list elements, <ul>
and <ol>
! These two sexy elements help millions of websites display lists of information in clean, semantic fashion. Without them, we’d be crawling around like filthy cavemen, eating dirt and howling at the moon.
But these list elements aren’t just sexy, they are also extremely flexible, enabling us humble designers to create robust list configurations that are semantically versatile and highly customizable. We all know how to throw down a basic list:
<ul>
<li>Pancakes</li>
<li>Bananas</li>
<li>Monkeys</li>
</ul>
Or even throw down some hardcore nested-list action:
<ul>
<li>Pancakes
<ol>
<li>Swedish</li>
<li>Blueberry</li>
<li>Chocolate</li>
</ol>
</li>
<li>Bananas
<ol>
<li>Manzano</li>
<li>Plantain</li>
<li>Cavendish</li>
</ol>
</li>
<li>Monkeys
<ol>
<li>Spider</li>
<li>Howler</li>
<li>Squirrel</li>
</ol>
</li>
</ul>
This nested list markup will result in a unordered bulleted parent list with numerically ordered nested lists, resulting in something like this in a browser:
- Pancakes
- Swedish
- Blueberry
- Chocolate
- Bananas
- Manzano
- Plantain
- Cavendish
- Monkeys
- Spider
- Howler
- Squirrel
Of course, we can style the display of this list configuration with some super-sexy CSS. For example, we can change the appearance of both ordered ( <ol>
) and unordered ( <ul>
) list markers by specifying one of the following types:
ul, ol {
list-style-type: none; /* no list marker */
list-style-type: disc; /* filled circles */
list-style-type: square; /* square markers */
list-style-type: circle; /* circle markers */
list-style-type: inherit; /* inherits style */
list-style-type: decimal; /* number markers */
list-style-type: decimal-leading-zero; /* 01, 02, 03, .. */
list-style-type: lower-alpha; /* a, b, c, d, .. */
list-style-type: lower-latin; /* a, b, c, d, .. */
list-style-type: lower-greek; /* alpha, beta .. */
list-style-type: lower-roman; /* i, ii, iii, .. */
list-style-type: upper-alpha; /* A, B, C, D, .. */
list-style-type: upper-latin; /* A, B, C, D, .. */
list-style-type: upper-roman; /* I, II, III, .. */
}
And, as if those options weren’t enough, CSS also enables us to use any list marker imaginable via the incredibly sexy list-style-image
property. For example, we could create a small GIF image of a banana and use it as a list marker with the following CSS:
ul, ol {
list-style-image: url(banana.gif);
}
This technique is also possible by setting a background-image
for the individual list ( <li>
) items, thereby providing a greater degree of presentational control:
ul li, ol li {
background-image: url(banana.gif);
}
We can even combine these methods to establish a built-in fallback mechanism that will enable the custom list-marker images to degrade gracefully to any list-style type. While we’re at it, let’s change the position of the list markers to appear within the list element itself:
ul {
list-style-image: url(banana.gif);
list-style-position: inside;
list-style-type: circle;
}
This will give us an unordered list that displays our custom banana.gif
marker if supported, else the list markers will be displayed as circles. Further, the list markers in this example will be displayed on the inside of the list items. To conserve resources, we may combine these three rules into the following “shortcut” declaration:
ul {
list-style: circle url(banana.gif) inside;
}
If we wanted to display the list without markers, there are two ways to prevent long strings of list text from extending past the first line, for example:
Lorem ipsum blah blah blah, Lorem ipsum blah blah blah,
Lorem ipsum blah blah blah, Lorem ipsum blah blah blah,
Lorem ipsum blah blah blah, Lorem ipsum blah blah blah,
Lorem ipsum blah blah blah, Lorem ipsum blah blah blah,
Lorem ipsum blah blah blah, Lorem ipsum blah blah blah,
Lorem ipsum blah blah blah, Lorem ipsum blah blah blah.
This case happens when the list-style-position
is set to inside
and the list text wraps onto subsequent lines. So, to alleviate this awkward list display, simply remove the list-style-position:inside
declaration or explicitly specify it as list-style-position:outside;
. Alternately, if you simply must use an inline display-type, you can prevent subsequent lines from “underlapping” the first line by using the oft-overlooked text-indent
property:
ul {
list-style-position: inside;
text-indent: -0.7em;
list-style: none;
}
The text-indent
technique is also useful when using generated content for your list markers. For example, by generating list markers with the following CSS:
ul {
list-style: none;
}
ul li:before {
content: "\00BB \0020";
}
You will see this for short list items:
- Pancakes
- Bananas
- Monkeys
And this for long list items:
- Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah. Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah.
- Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah. Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah.
- Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah. Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah, Lorem ipsum blah blah blah.
Ugh! There’s that nasty underlapping text wrap again. This happens because the generated content is inserted within the list elements. Unfortunately, setting the display-type to outside
does not help in this scenario. Fortunately, we can easily resolve this issue by including a text-indent
declaration to our previous list styles:
ul {
text-indent: -1em;
list-style: none;
}
ul li:before {
content: "\00BB \0020";
}
Problem solved. At this point, you may be thinking, “what’s with all of that funky ‘generated content’ stuff?” If so, allow me to explain.
CSS 2.1 provides us with tools that enable us to insert various types of content into our markup. By combining the :before
or :after
pseudo-selectors and the content
property, we can add alphanumeric and special characters into our document via the stylesheet. The characters that may be inserted may be alphanumeric text strings or escaped hexadecimal character equivalents such as the following:
\0020
— blank space, unicode =\21D3
— down arrow, unicode =⇓
( ⇓ )\00BB
— right double angle quote, unicode =»
( » )
But wait, there’s more! Using CSS may be the modern, “Web-Standards” way of configuring the presentation of list elements, but there are also some interesting and useful inline tricks that, although deprecated, prove a delightful romp nonetheless. Let’s peek into the past, shall we?
First, the list-style type
property may be specified inline for <ul>
(and even <li>
) elements:
<ul type=circle>
<li>Telegraph</li>
<li>Telephone</li>
<li>Mobile phone</li>
</ul>
For unordered lists, the accepted values are circle
, square
, and disc
. For ordered lists, the accepted property values are A
, a
, I
, i
, and 1
. Here is an example:
<ol type=A>
<li>Atari</li>
<li>Nintendo</li>
<li>Playstation</li>
</ul>
Here is a breakdown of the accepted values for the type
property:
circle
— circle markerssquare
— square markersdisc
— disc markersA
— uppercase lettersa
— lowercase lettersI
— uppercase romani
— lowercase roman1
— default markers
That’s all fine and well, but something that is far more useful is the ability to set specific values for various list items. By using the deprecated value
attribute applied to the <li>
element, we may set marker values as in the following example:
<ol>
<li value=3>The marker for this item is the number 3</li>
<li>The marker for this item is the number 4</li>
<li>The marker for this item is the number 5</li>
<li value=11>The marker for this item is the number 11</li>
<li>The marker for this item is the number 12</li>
<li>The marker for this item is the number 13</li>
</ol>
..which looks like this:
- The marker for this item is the number 3
- The marker for this item is the number 4
- The marker for this item is the number 5
- The marker for this item is the number 11
- The marker for this item is the number 12
- The marker for this item is the number 13
We can do something similar by using the start
attribute, which enables us to specify the initial value of an ordered list. Here is an example:
<ol start=77>
<li>The marker for this item is the number 77</li>
<li>The marker for this item is the number 78</li>
<li>The marker for this item is the number 79</li>
</ol>
..which produces this:
- The marker for this item is the number 77
- The marker for this item is the number 78
- The marker for this item is the number 79
This seems incredibly useful, such that I wonder if there is an equivalent way to accomplish this using modern methods, CSS and/or HTML.
One final trick before I close — older versions of HTML enable you to create “compact” lists using the compact
attribute:
<ol compact>
<li>Business</li>
<li>Pleasure</li>
<li>Nonsense</li>
</ol>
The idea here is that any list featuring the compact
attribute will be displayed in a more compact fashion in the browser. Instead of applying the usual margin and padding to the list and its various items, the browser will reduce the amount of these properties to render a tighter, more “compact”-looking list.
Okay so I’ve got one more “sexy” trick for HTML lists: reversing the order of the numbers. Just add the reversed
attribute, like so:
<ol reversed>
<li>Coffee</li>
<li>Whiskey</li>
<li>Cool Aid</li>
<li>Diet Coke</li>
<li>Slurpeee</li>
</ol>
So that will reverse the order of the list items to look like this:
- Coffee
- Whiskey
- Cool Aid
- Diet Coke
- Slurpeee
So the list items will remain in the same order, but the numbers will be in reverse order. Possibly useful for shopping lists, favorite movies lists, and showing off how awesome HTML can be :)
Later days..
That does it for this fun-filled episode of Sexy HTML List Tricks — stay tuned for more exciting content from Perishable Press.
24 responses to “Sexy HTML List Tricks”
“Or even throw down some hardcore nested-list action:…”
I like your style, to quote Starsky and Hutch.
Sweet tips!
Thanks, hopefully I didn’t cut too loose on this one — sometimes it feels good to open up and let it hang.
Chills :)
Excellent useful clear simple and accessible as always :)
Hi Jeff,
I loved the tips. But i have one doubt regarding the semantic markup correctness of this approach. I have just implemented this tips in one of my page where there was a need to reverse the order of the list items within an ordered list. ie, after 5 i needed 10 to appear and then in the descending order till 6. I wonder if giving the ‘value’ attribute is a gud idea in this instance. Please advice. My concern is just that, is this semantically correct markup ?
Cheers!
mysticpixels
Nice examples, there are some nice stuff that isn’t so well known about OLs in there. But the first thing I thought looking at it was:
wouldn’t be a definition list with nested OLs semantically more suitable for your pancakes/bananas/monkeys example?
That was a v gud explanation. Thax a ton ‘That guy’ :). Btw, which guy are u ;)
@MysticPixels:
The idea of semantics on the web is to create markup that is understandable by machines, so we can offload the tedious work of searching to them.
Let’s say you create a list like you described (I’ll give each a letter as text):
1-a, 2-b, 3-c, 4-d, 5-e, 10-f, 9-g, 8-h, 7-i, 6-j
If you asked for the value of the list-item that contained “f” you would get “10” no matter what. Even though “f” actually appears in 6th position, the VALUE of that list-item is still “10.”
Likewise, if you asked for what was displayed in the 10th element of the list, the computer would show you “f” because “f” is assigned to the list-item with a value of “10.”
The machine doesn’t care WHERE you decide to show your list items, it’s the VALUE that holds importance.
In other words, the machine will always see the list like this:
1-a, 2-b, 3-c, 4-d, 5-e, 6-j, 7-i, 8-h, 9-g, 10-f
As an extreme example the following list is perfectly semantic:
5-e. 8-g, 3-c, 6-j, 1-a, 9-g, 10-f, 2-b, 4-d, 7-i
So, short answer to your question: using value=”” on each item is fine =D
@Kristof: Yes, good point. I suppose it all depends on the context. I was going to include definition lists into the mix, but decided to keep the article as short as possible ;)
@That Guy: Excellent response! Thank you :)
Very interesting and amusing subject. I read with great pleasure.
I like using little shiny gold balls or gel icons. They do add a whole new Oomph to the overall design
Excellent article. I had no idea you could use this “content: “0BB 020″;” at all. Nor the “start” attribute as well. Excellent refresher Jeff, thanks :)