CSS Counters – The Right Way to Organize Your Ordered Content

via CSS Counters – The Right Way to Organize Your Ordered Content.

It is pretty common to see step-based content. Tutorials, shopping carts, FAQ’s, grandma’s recipes. You know, numbers and steps are really good to grab attention, so many writers use this.

But, talking about HTML how should we write it? Most (all?) use numbers as text in headings, as they were common content.

Well, let me tell you a secret: They are doing it wrong.

Actually we are doing it wrong ( nothing against this fantastic post of Ruben, just take a look at how we do the numbers, directly in HTML as text ).

A little time ago I was wondering about this thing, isn’t it more a CSS job? Actually yeah, it is. We have to keep content in HTML and presentation in CSS, and since we may want other ways to order titles, they are all about presentation. But, how can we do this kind of thing? One class for each item? That would be terrible!

Then CSS counter property comes to save us. It is a pretty unknown property that allows us to perform a simple count via CSS. It will be better explained with our demos 😀

So, let’s rock!

CSS Counters – The Right Way to Organize Your Ordered Content


Take a look at what you will do at the end of this tutorial:

I think you should check out the demo, and download it to try out a little bit more!

So, counter?

Basically a counter is a “variable” that we can create with CSS but the only two possible operations that we can perform with it is to increase or to reset. For such operations we can use counter-reset or counter-increment CSS properties.

A basic usage is the first case mentioned in this post, the organized content. So let’s say you have a multi-step tutorial and want it organized automatically, what you have to do is just add this to your CSS:

  1. body {
  2. counter-reset: first; /* our h1's counter is zero every time we have a body tag (hope only once) */
  3. }
  4. h1 {
  5. counter-increment: first; /* so, when we have one h1, our counter will increase one unit */
  6. counter-reset: second; /* and we will reset our h2's counter */
  7. }
  8. h1:before { /* wow, here we will append a pretty formated Step N - Item */
  9. content: "Step " counter(first) " - "; /* when you write counter(first) we will get its current value */
  10. font-size: 0.8em;
  11. font-weight: normal;
  12. font-style: italic;
  13. color: #bababa;
  14. }
  15. h2 {
  16. counter-increment: second; /* so our h2's counter goes up.. */
  17. counter-reset: third; /* and we reset the h3's */
  18. }
  19. h2:before {
  20. content: counter(first) "." counter(second) " - "; /* we will output H1NUMBER.H2NUMBER */
  21. }
  22. h3 {
  23. counter-increment: third; /* h3 goes up, up, up */
  24. }
  25. h3:before {
  26. content: counter(first) "." counter(second) "." counter(third) " - "; /* and we output H1.H2.H3 */
  27. }
As you can see its usage is quite simple. Our downside is that we rely on content: property and after (or before) pseudo-element so older browsers won’t see this. But it should work just fine in IE8+ and other browsers.

Multiple counters

Another great thing is that you can have a “general” counter, you just have to separate multiple counters to increase with spaces. Just like this:

1 body {
2 counter-reset: general first;
3 }
4 h1 {
5 counter-increment: general first;
6 counter-reset: second;
7 }
8 h2 {
9 counter-increment: general second;
10 counter-reset: third;
11 }
12 h3 {
13 counter-increment: general third;
14 }

Better Ordered lists

Using almost the same code, you can create better ordered lists, with sub-items control.  So instead of just 1 – ITEM you can have – ITEM when you have multiple nested OL’s. This is the code I’d use:

1 ol {
2 list-style: none;
3 counter-reset: olfirst; /* our father OL must have olfirst item reseted */
4 font-family: arial;
5 }
6 ol ol {
7 counter-reset: olsecond; /* our sub OL's reset the olsecond, third must to be olthird and so on */
8 }
9 ol li {
10 counter-increment: olfirst; /* when we have a item that is children of first OL, it increases first counter*/
11 }
12 ol li ol li {
13 counter-increment: olsecond; /* when the item is children of a OL that is children of another OL, so it is a sub OL */
14 }
15 ol li:before {
16 content: counter(olfirst) " - "; /* let's output our pretty number */
17 }
18 ol li ol li:before {
19 content: counter(olfirst) "." counter(olsecond) " - "; /* let's output our "sub-number" */
20 }

Are you hungry yet?

This is a pretty tricky attribute so you must to try it out a couple of times until you are familiar with it. But we have some tutorials at W3Schools about CSS counter reset, CSS counter increment and beforeafter pseudo elements that can help you a lot.