Grow your CSS skills. Land your dream job.

Numbering In Style

Published by Chris Coyier

Chances are if you want to number things in order on a website, the ordered list (<ol>) is your guy. It also is pretty reasonable that you want to style those numbers. Strangely enough, styling those list numbers isn't a very easy thing to in CSS. Thankfully it's also not impossible. Roger Johansson has a tutorial that shows how it can be done with the :before pseudo element, which can have a counter as a value to the content property.

But let it be known, applying numbered counters is not limited to ordered lists. For instance, let's say you wanted to number the question and answer pairs of a FAQ list.

You'd have markup like this:

<dl class="faq">

	<dt>How much wood would a wood chuck chuck if a wood chuck could chuck wood?</dt>
	<dd>1,000,000</dd>
	
	<dt>What is the air-speed velocity of an unladen swallow?</dt>
	<dd>What do you mean? An African or European swallow?</dd>
	
	<dt>Why did the chicken cross the road?</dt>
	<dd>To get to the other side</dd>
	
</dl>

Each new <dt> element is a new question, hence where we should apply the numbering. It's as simple as this:

.faq {
	counter-reset: my-badass-counter;
}
.faq dt:before {
	content: counter(my-badass-counter);
	counter-increment: my-badass-counter;
}

Style the :before element as you will. For instance:


View Demo

Just wanted to make ya'll aware of this ability. You start thinking of all kinds of things to number once it's sunk in. For instance I recently blogged one of my favorite recipes and I numbered each step/photo with blocky roman numerals.

Which reminds me: the numbers don't have to be decimals. They can be anything that list-style-type can be. Namely:

disc (• • •)
circle (○ ○ ○)
square (▪ ▪ ▪)
decimal (1 2 3)
decimal-leading-zero (01, 02, 03)
lower-roman (i ii iii)
upper-roman (I II III)
lower-greek (α β γ)
lower-latin (a b c)
upper-latin (A B C)
armenian (Ա Բ Գ)
georgian (ა ბ გ)
lower-alpha (a b c)
upper-alpha (A B C)

All you need to do is specify which in the counter value itself:

content: counter(my-counter, lower-roman);

The Future

The stuff above is cool and in the Use-It-Today™ camp. But it almost feels hacky when you look at the leap forward CSS3 lists is taking. Once browser support for that comes along, we'll be able to do things like target the marker of the list at will:

/* 
  Examples from THE FUTURE
  No browser support at the time of this writing 
*/

li::marker { 
  width: 30px;
  text-align: right;
  margin-right: 10px;
  display: inline-block;
}

ol { 
  list-style: symbols("*" "\2020" "\2021" "\A7"); 
}

ul { 
  list-style-type: "★"; 
}

Comments

  1. Great take on lists and definitions! I could see a lot of cases where this will come in handy.

  2. Permalink to comment#

    I had no idea that this could be accomplished in pure CSS – awesome tutorial (as always) Chris!

  3. Permalink to comment#

    Hi can you add (post) a HTML and CSS code for the first picture (image) ?
    I like design that you can see on first picture.
    Thanks.

  4. DJ
    Permalink to comment#

    Chris… according to Wolfram Alpha (their source is given) – a Woodchuck can chuck 361,9237001 cubic centimeters of wood – (if he could chuck wood that is) – NOT the “1,000,000” which you list. Just FYI, in case you feel like correcting your obviously inadvertent faux pas.

    ps – glad you are back and moving on with your life: we missed you!

    • DJ
      Permalink to comment#

      Obviously that’s 361.9237001 cc/day.

    • Scott Vivian
      Permalink to comment#

      Sorry, the correct answer is in fact, “a chuckload”.

    • MarkV
      Permalink to comment#

      The correct answer is actually:
      The wood that a woodchuck would chuck. Is the wood that a woodchuck could chuck. If a woodchuck could chuck wood.

  5. Ade
    Permalink to comment#

    I’ve used this quite a lot in the last couple of years or so, when appropriate because it’s great for appearance and very flexible.

    But it’s well worth noting that having to set the list-style-type to none means that it is really only suitable for content that you just what to style like a list.

    Anything that actually should be a list should not have its list-style removed if you can avoid it because it significantly reduces semantic understanding in most ATs.

  6. I recently had a project that required a “countdown.” I used this technique to make the list count backwards (from 10 to 1):

    
    ol.backwards > li {
        counter-increment: item -1;
    }
    ol.backwards > li:before{
        content: counter(item) ". ";
    }
    
  7. TeMc
    Permalink to comment#

    $trade; => &trade;

  8. Permalink to comment#

    Wow. This is very new for me :(o)

  9. Permalink to comment#

    Nice ! Thanks

  10. Whats compatibility like with this?

  11. Andy
    Permalink to comment#

    Very useful to know, however why are the ingredients for your meatloaf recipe not marked up as a list?

  12. Permalink to comment#

    nice dude ! thanks a lot !

  13. Edward
    Permalink to comment#

    I learn something new everyday! Thanks for the tip!

  14. Permalink to comment#

    I’m loving this idea, I stumbled upon it myself recently while trying to get the left padding equal on the list item content, trying to get “hello” to line up vertically:

    6 hello
    66 hello
    666 hello

    but using :before we can welcome in :inline-block and set a width!

    http://jsfiddle.net/sQaeR/

  15. Chris, I checked out counter-reset CSS property, and W3Schools says that it belongs to CSS2. How weird is that this property is so lost between designers.

    To be honest, this was my first time I met this property. Do you have a reference to the W3’s specification, in which this property is defined?

  16. Laura
    Permalink to comment#

    This is a really helpful post but it requires one correction:

    a woodchuck would chuck as much wood as he could chuck if a woodchuck could chuck wood.

  17. Great article Chris! I actually published a similar (relatively) article a couple of days ago – Use :pseudo-elements as list-style-image alternatives.

  18. Good to know, Thanks Chris!

  19. Adam
    Permalink to comment#

    For people asking about the compatibility for this, it’s fine in all major browsers except IE7 (and before). IE7 doesn’t support the :before/:after pseudo elements.

    But IE7 is under 5% worldwide!!!!

    http://gs.statcounter.com/#browser_version-ww-monthly-201111-201111-bar

  20. Great and very useful.
    Thanks

  21. Great article; looks like the future of CSS3 lists is going to be worth keeping an eye on.

    Spotted a typo: “One browser support for that comes along” -> “Once browser support…”

  22. Permalink to comment#

    Great tut, nice stuff as always

  23. Permalink to comment#

    nice article ..

    i found this type of article from few days..

  24. Mido Ghranek
    Permalink to comment#

    I tried many methods to Get Countdown Automatically but nothing worked, any Ideas for it?

  25. If anyone is looking for more inspiration for custom lists that use this technique, check out this post!

  26. Josh Simpson

    This technique is not highly recommend due to the WCAG 2.0 requirements in Web Accessibility. How does the deaf / blind user would know that list is actually #1 out of 3 when this technique doesn’t generate the actual text or value that has the number in it. I would highly discourage using this technique.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".