Avatar of Geoff Graham
Geoff Graham on (Updated on )

The counter-set CSS property, true to its name, sets the starting value for a CSS counter. You know how ordered lists start at 1 and then increment up from there? The counter-set property allows us to set that starting value to something else, say, -1. Or 2. Or 200! Except that it is applied to CSS counters instead of ordered lists.

So, let’s say we have a custom counter for a list of book chapters, where the chapter number is prepended to the chapter name.

We’d start by defining a counter with the counter-reset property. We’ll call it chapter and define it on a parent container class for our chapters called, creatively, .chapters.

.chapters {
  counter-reset: chapter;

Next, we’d assign the chapter counter to an element using the counter-increment property. Since these are book chapters, we’ll apply them to <h2> elements, assuming the book title would be the <h1>. Notice that we’re actually assigning it to the :before pseudo-element since it allows us to prepend our counter to the actual <h2> element.

h2:before {
  counter-increment: chapter;

Cool, the last thing we would need is to tell the counter what it should display. That’s done on the content property via the counter() function. We’ll throw a little color on the counter as well since the design calls for it.

h2:before {
  color: red;
  content: "Chapter " counter(chapter) ": ";
  counter-increment: chapter;

Hey, we’re looking good!

But wait! I’m not really digging the fact that we’re starting on Chapter 1. I mean, the “Forward” isn’t really a chapter. If anything, it’s like Chapter 0.

That’s where counter-set comes in! Let’s set things to start at zero:

h2:first-of-type::before {
  counter-set: chapter;

There we go! That’s better. Just by setting the property value to the name of the counter, we’ve set the list of chapters to start at Chapter 0. We could have just as easily set it start at something else, like chapter 100.

And if a browser doesn’t support counter-set? Nothing, really. It will simply be ignored and the list will start at its default, 1.


[ <custom-ident> <integer>? ]+ | none

This is basically a fancy way of saying the property takes the name of a custom counter (<custom-ident>) and the starting value (<integer>). Or set it to none and the numbering will start at the default starting point, 1.

  • Initial value: none
  • Applies to: all elements (including non-visual ones)
  • Inherited: no
  • Animation type: by computed value type


/* Set "awesome-counter" to 0 */
counter-set: awesome-counter;

/* Set "awesome-counter" to -10 */
counter-set: awesome-counter -10;

/* Set "awesome1" to 0, and "awesome2" to 2 */
counter-set: awesome1 awesome2 2;

/* Wipe out any other settings that may have been declared elsewhere */
counter-set: none;

/* Global values */
counter-set: inherit;
counter-set: initial;
counter-set: unset;

Note that counter-set will create a new counter if the counter name declared on it has not already been defined somewhere else.

Browser support

Android ChromeAndroid FirefoxAndroid BrowseriOS SafariOpera Mini
Source: caniuse

Further reading