Styling Ordered Lists with CSS Counters

Introduction

Here's a scenario I find myself in now and then: I want an ordered list, and I want it to be pretty.

Because semantic HTML is important, I reach for the trusty <ol> tag:

html
  1. Stop
  2. Drop
  3. Roll

The problem is that the "bullets" (the prefix numbers) are in a CSS-selector dead zone. There is no way to style them independently!

I am not one to accept lackadaisical bullets. So I did some digging, and found an awesome solution 🎉.

Link to this heading
Counters to the rescue

CSS has a pretty nifty trick up its sleeve to deal with this situation. It has a built-in counter mechanism.

Here's how that looks:

css

Let's go through this step by step:

  1. counter-increment is a CSS property that will increment a specific "counter" variable whenever it encounters a new element. We put it on every ordered-list item. I named my variable "muffins", because I like muffins.
  2. Before each ordered-list item, I display the current value of the count. counter() can be thought of as a CSS function which returns the value for a specific counter. In this case, muffins.
  3. I remove the default uncustomizable bullets with list-style: none, and specify a counter reset. This ensures that if I have multiple <ol> elements on a page, the counter will reset for each one.

With this CSS, we've effectively recreated a default <ol>. The difference is that we now have a CSS selector, ol li:before, we can use to apply custom styles.

Here's how ordered lists look on this blog, using this trick:

Link to this heading
How to bake a cake

  1. I think you do something with dry ingredients
  2. The mixers play a role here
  3. Combine everything while crossing fingers
  4. Transfer to oven
  5. Poke with toothpick for fun, and then serve

It's not night-and-day, but I'm very pleased with the overall effect!

Link to this heading
Browser support

CSS counters feel like a next-gen feature, but actually they've been around forever. They're supported in Internet Explorer 8!!

Use this property without guilt ✨

Link to this heading
This seems like a lot of trouble!

The CSS Working Group agrees—they've penned a draft for a new ::marker pseudo-element, which would let you apply styles directly to list bullets.

Unfortunately, this is only available in Firefox and Safari.

Also: there's one more trick CSS counters have up their sleeves…

Here's the really cool thing: counter has a cousin, counters, and it works for nested lists.

Notice how the numbering stacks recursively, in this awesome-sounding curriculum:

Here's the CSS necessary for this:

css

It's super similar, except you use counters instead of counter, and you add an "intermediary" spacer (in this case, a period).

Link to this heading
Bringing Order Back

The ol doesn't get a lot of love compared to the ul. And yet, people love counting things! Something doesn't add up.

Maybe with this neat trick, we'll finally see ol get the attention it deserves.

Last Updated

April 7th, 2020

Hits

A front-end web development newsletter that sparks joy

My goal with this blog is to create helpful content for front-end web devs, and my newsletter is no different! I'll let you know when I publish new content, and I'll even share exclusive newsletter-only content now and then.

No spam, unsubscribe at any time.



If you're a human, please ignore this field.