Create a Cool Messy List with CSS3 and nth-child
While working on a design recently, I stumbled upon Chris Coyier’s article How nth-child Works. Chris shows us the basics of the nth-child pseudo-selector in CSS. It can be used for so many things, but in this short tutorial I’m going to show you how to create a cool messy list.
First, check out the demo to see what we’re creating in the demo.
We’re going to start with an HTML5 document (why not?), and include a stylesheet, as shown below:
<h1>Messy List</h1> <!DOCTYPE HTML> <html lang="en"> <head> <meta charset="utf-8"> <title>Messy List</title> <link rel="stylesheet" href="style.css" /> </head> <body> <header> <h1>Messy List</h1> </header> <section> <ul> <li>Lorem ipsum dolor sit amet</li> <li>Duis aute irure dolor in reprehenderit.</li> <li>Excepteur sint occaecat cupidatat.</li> <li>Ut enim ad minim veniam.</li> </ul> </section> <footer> <p>Copyright © 2010</p> </footer> </body> </html>
That’s a pretty simple HTML document—and of course the most important part is the list. Next, here’s the stylesheet (with an HTML5 CSS reset in it as well). You can get the background from SeamlessTextures. I’ve modified it in color and size, so you can also just get my version.
/* HTML 5 Reset */ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-size: 100%; vertical-align: baseline; } body { line-height: 1; } table { border-collapse: collapse; border-spacing: 0; } section, article, aside, header, footer, nav, dialog, figure { display:block; } body { background: url(background.png); width:600px; margin: 40px auto 0; font-family: Georgia, serif; color: #333333; } h1 { font-size: 3em; margin-bottom:1em; } ul { list-style: none; } ul li { padding: 8px 15px; margin: 10px 0; } ul li:nth-child(odd) { background: rgba(50,50,50,0.1); } ul li:nth-child(odd):hover { background: rgba(50,50,50,0.3); } ul li:nth-child(even) { background: rgba(50,50,50,0.3); } ul li:nth-child(even):hover { background: rgba(50,50,50,0.5); } ul li:nth-child(3n+1) { -webkit-transform:rotate(-0.6deg); -moz-transform:rotate(-0.6deg); transform:rotate(-0.6deg); } ul li:nth-child(3n+2) { -webkit-transform:rotate(0.5deg); -moz-transform:rotate(0.5deg); transform:rotate(0.5deg); } ul li:nth-child(3n+3) { -webkit-transform:rotate(0.2deg); -moz-transform:rotate(0.2deg); transform:rotate(0.2deg); }
I guess there’s not much new for you here, but let’s break it down a bit anyway. First, we define the width of our body to be 600px. Also, we include the aforementioned background, specify font and color, and add a top margin. Next, we define the size of our H1. And now comes the fun part.
We remove the dots from our list with list-style: none;, and add a little padding to our list elements. We’ll look at the nth-child selectors in bits. Check out the first one:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ul li:nth-child(odd) { background: rgba(50,50,50,0.1); } ul li:nth-child(odd):hover { background: rgba(50,50,50,0.3); } ul li:nth-child(even) { background: rgba(50,50,50,0.3); } ul li:nth-child(even):hover { background: rgba(50,50,50,0.5); } |
We choose every second li element, and add a background to it. In this case, we choose a dark gray, and set the opacity to 0.1 (RGBA is new in CSS3), so we can see the background through the li elements. We do exactly the same for our even elements, with the opacity set to 0.3. This is just basic zebra striping. You can add several selectors to an element, so we also add a hover background color a little darker than the original element.
Next, we target 3n+1—that is, every third element, starting with the first.
1 2 3 4 5 | ul li:nth-child(3n+1) { -webkit-transform:rotate(-0.6deg); -moz-transform:rotate(-0.6deg); transform:rotate(-0.6deg); } |
We rotate the list element by -0.6 degrees. We do the same thing for both 3n+2 (every third element, starting with the second) and 3n+3 (you get the idea). By rotating every third element, and doing zebra striping with every second element, the list seems sort of random, which, I think, is a really cool effect.
If you use Safari, Firefox or Chrome, this is what you should have:

UPDATE: You can target Opera with the following (thanks to ToMzorz):
1 | -o-transform:rotate(-0.6deg); |
You can also check out the demo again, or download the source code.
Thanks for reading.
Endy
August 2, 2011 at 2:38 pmvery awesome tutorial … I was very lucky to find this site .. thanks .. and fantastisch..
thomaso
July 5, 2011 at 4:06 pmGreat effect and we utilized it on our website in a few places (http://www.franklinlevy.com). But, the messy list looks choppy in Firefox. Do you know why? How can I fix this? In Chrome it looks nice and neat.
ฟังเพลง
June 12, 2010 at 2:16 pm*0*
cool!
Ahmad Alfy
April 23, 2010 at 2:36 amNow this is something that looks urban and great
Rock on Peter
Michael
April 21, 2010 at 12:34 pmGreat post Peter, but I’m trying to do an alternate comment backgrounds in WP 2.9.2 for the last three days and nothing is working. Can you point me in the right direction for something that does work with 2.9? Enjoyed your site, will be back often–
ToMzorz
April 16, 2010 at 8:04 pmYou forgot about Opera 10.5:
so correctly (check the others too):
ul li:nth-child(3n+1) {
-webkit-transform:rotate(-0.6deg);
-moz-transform:rotate(-0.6deg);
-o-transform:rotate(-0.6deg);
transform:rotate(-0.6deg);
}
Btw great tutorial, used it here: http://tomzorz.me/projects/ (still filled up with dummy stuff)
Peter
April 17, 2010 at 8:50 amThanks, dude!
I completely forgot about Opera.
Jireck
April 15, 2010 at 5:28 pmGood … Use of CSS3!!
Ken
April 15, 2010 at 3:25 pmwow, fantastic tutorial! too bad CSS3 is not implemented yet in IE and HTML5 also.