Thoughts about React,Web Development,Performance

October 21, 2021

CSS Counters

Giovanni Benussi
@giovannibenussi

CSS custom properties, also known as CSS variables allow us to define custom properties, or variables to use in our CSS.

CSS counters are variables that you can use in your code. You can use counters to display things like heading and code block line numbers.

One real-world use case for counters is to display line numbers in code blocks. The good think about this approach is that it doesn't require Javascript so you don't need to deal with internal logic to update styles.

Our First Counter

Let's start with an example followed by a step-by-step explanation:

.demo {
  counter-reset: paragraph-counter;
}

.demo p::before {
  counter-increment: paragraph-counter;
  content: "Paragraph " counter(paragraph-counter) ": ";
}

This counter displays "Paragraph x" before each paragraph. Let's try it out with the HTML code from below.

<p>First paragraph</p>
<p>Second paragraph</p>
<p>Third paragraph</p>

This produces the following output:

First paragraph

Second paragraph

Nested paragraph

Third paragraph?

Let's see what happens with nested paragraphs:

<p>First paragraph</p>
<p>Second paragraph</p>
<div>
  <p>Nested paragraph</p>
</div>
<p>Third paragraph?</p>

First paragraph

Second paragraph

Nested paragraph

Third paragraph?

As you can see, it considers nested paragraphs too because our CSS rule increments the count on every p tag. If you rather want to increment the counter only on top level paragraphs, you'd need to increase the specifity of your CSS by selecting only direct descendants of your parent element (changing .demo p to .demo > p) as shown below:

.demo {
  counter-reset: paragraph-counter;
}

.demo > p::before {
  counter-increment: paragraph-counter;
  content: "Paragraph " counter(paragraph-counter) ": ";
}

The change above produces the desired result:

First paragraph

Second paragraph

Nested paragraph

Third paragraph?

Now that you have a basic understanding, I'll detail and introduce CSS properties to work with counters.

counter-reset

We can specify an initial value to counter-reset:

counter-reset: paragraph-counter 5;

First paragraph

Second paragraph

Nested paragraph

Third paragraph?

Also works with negative numbers:

counter-reset: paragraph-counter -5;

First paragraph

Second paragraph

Nested paragraph

Third paragraph?

You can reset multiple counters at the same time:

counter-reset: paragraph-counter 5 another-counter 10;

counter-increment

You can increment a counter by an arbitrary value:

counter-increment: paragraph-counter 5;

If no value is specified, it will default to 1.

counter-set

counter-set sets a counter to a given value.

counter-set: paragraph-counter 5;

If you don't specify a value, it will default to 0:

/* Set paragraph-counter to 0 */
counter-set: paragraph-counter;

Conclusion

CSS counters allow to do things that were only possible with Javascript a few years ago. I recommend you to take a look at places where you can start using counters!