Did you know that CSS Counters can go backwards?
Neither did I until I needed it, and I discovered that the counter-reset
and counter-increment
properties can be “seeded” with extra numbers, intended to allow for more flexible numbering, which can also be used to make them count backwards!
Counting Forwards
The basic idea with counters is that they allow you to implement number-systems in CSS, essentially replacing and supplementing ordered-list attributes like value
and start
. With two properties, you declare the name of a counting variable in a base selector, then increment it in an instance selector; the result is then typically output using the content
property. Here’s a simple example, that re-creates the numbering of a standard ordered-list (example1):
ol
{
list-style-type:none;
counter-reset:item;
}
ol > li
{
counter-increment:item;
}
ol > li:before
{
content:counter(item) ". ";
}
But as I said earlier, you can “seed” both these properties with additional values, so that they start from a different number and/or count in different steps. Here’s another example, this time starting from ten and counting up in twos (example2):
ol
{
list-style-type:none;
counter-reset:item 10;
}
ol > li
{
counter-increment:item 2;
}
ol > li:before
{
content:counter(item) ". ";
}
Counting Backwards!
Now here’s the cunning bit! The additional value in counter-increment
doesn’t have to be positive, it can also be zero or negative. So here’s an example of a counter that goes backwards from ten to one (example3):
ol
{
list-style-type:none;
counter-reset:item 11;
}
ol > li
{
counter-increment:item -1;
}
ol > li:before
{
content:counter(item) ". ";
}
The thing to note is how we have to start counter-reset
one-count higher than the highest number we want to display, because the iterating property counter-increment
has already counted once when the first element is displayed (it’s counted that element).
Of course the fact that we have to hard-code the starting number at all makes this difficult to use in the wild, because the lists it encounters will generally have different numbers of items. The thing to do then is split the rules between a stylesheet and an inline style
rule.
Production Code
So first we have the following stylesheet rules, which define an activating class
, and the counting rule (there are also a couple of CSS hacks for IE6 and IE7, to restore their normal list-style
since the counters won’t work):
ol.count-backwards
{
list-style-type:none;
}
ol.count-backwards > li
{
counter-increment:start-from -1;
}
ol.count-backwards > li:before
{
content:counter(start-from) ". ";
}
* html ol.count-backwards { list-style-type:decimal; }
*+html ol.count-backwards { list-style-type:decimal; }
Then we instantiate a counter instance with a counter-reset
style
, defining the starting number (or rather, one-higher than the starting number, as we’ve seen). I’ve used "start-from"
as the counter name so that it’s easy to remember what it is and what it does (example4):
<ol class="count-backwards" style="counter-reset:start-from 11">
<li>In tenth place..</li>
<li>In ninth place..</li>
<li>In eighth place..</li>
<li>In seventh place..</li>
<li>In sixth place..</li>
<li>In fifth place..</li>
<li>In fourth place..</li>
<li>In third place..</li>
<li>In second place..</li>
<li>In first place..</li>
</ol>
We can even define additional class
rules to implement different types of counter. Here’s one for lower-case greek (example5):
ol.count-backwards.lower-greek > li:before
{
content:counter(start-from, lower-greek) ". ";
}
But what’s it all for? Well, I wanted to make an archive list of blog posts for my site, listing the most-recent at the top. Since the first and earliest is then at the bottom, this means that the list needs to count down.
And I’m sure you can think of your own situations where this might be useful, and handy to have a way of implementing instantly, without the inevitable output-lag of doing it with scripting.
If the lack of IE6/7 bothers you, you could always add a scripting layer as well…
Afterthought: Hacking IE
Or at a pinch, you could do it with an expression
property (something I’ve written about before), and leverage the <ol>
start
attribute for IE to read the start number from (example6):
<ol start="10" class="count-backwards" style="counter-reset:start-from 11">
ol.count-backwards li
{
zoom:expression(
(typeof counter == "undefined"
? counter = parseInt(this.parentNode.getAttribute('start'), 10)
: counter--),
this.innerHTML = (typeof this.processed == "undefined"
? ("<strong>" + counter + ". </strong>")
: "")
+ this.innerHTML,
this.style.marginLeft = "-1.5em",
this.processed = true,
this.runtimeStyle.zoom = "1"
);
}
IE8 will ignore this code since it no longer implements expression
, but then it supported the counters in the first place! Woo-hoo!
Thumbnail credit: stephenvance
Frequently Asked Questions about Making CSS Count Backwards
How can I use CSS counters to count elements backwards?
CSS counters are a powerful tool that can be used to count elements in a variety of ways, including backwards. To count elements backwards, you can use the ‘counter-reset’ property to set the initial value of the counter to the total number of elements you want to count. Then, use the ‘counter-increment’ property with a negative value to decrement the counter for each element. Here’s a simple example:body {
counter-reset: section 10; /* Set initial counter value */
}
div::before {
counter-increment: section -1; /* Decrement counter */
content: counter(section);
}
Can CSS detect the number of children an element has?
CSS itself does not have a built-in way to directly detect the number of children an element has. However, you can use CSS counters to create a workaround. By setting a counter on the parent element and incrementing it for each child, you can effectively count the number of children. However, this method does not allow you to use the count in a CSS selector or property, it can only be displayed using the ‘content’ property.
How can I style a parent element based on its number of children using CSS?
Styling a parent element based on its number of children is not directly possible with CSS. CSS is designed to avoid parent selectors because they can lead to performance issues. However, you can use JavaScript to add classes to the parent element based on the number of children it has, and then style those classes with CSS.
What is the purpose of the ‘counter-reset’ property in CSS?
The ‘counter-reset’ property in CSS is used to create or reset a counter. It sets the counter to a specific value, which is usually zero, but can be any number. This property is often used in conjunction with the ‘counter-increment’ property to create numbered lists or to count elements.
How can I use CSS counters to create a numbered list?
CSS counters can be used to create custom numbered lists. You can use the ‘counter-reset’ property to create a counter and set its initial value, and then use the ‘counter-increment’ property to increment the counter for each list item. The ‘content’ property can then be used to display the counter value before each list item. Here’s an example:ol {
counter-reset: list-counter;
}
li::before {
counter-increment: list-counter;
content: counter(list-counter) ". ";
}
Can I use CSS counters to count elements in a specific order?
Yes, you can use CSS counters to count elements in a specific order. The order in which elements are counted is determined by the order in which they appear in the HTML document. If you want to count elements in a different order, you will need to rearrange the HTML elements or use JavaScript.
Can I use CSS counters with pseudo-elements?
Yes, CSS counters are often used with pseudo-elements like ::before and ::after. The ‘content’ property, which is required for these pseudo-elements, can be used to display the counter value.
Can I use multiple CSS counters at the same time?
Yes, you can use multiple CSS counters at the same time. Each counter is independent and can be incremented or reset separately. This can be useful for creating complex numbering systems or for counting multiple types of elements.
Can I use CSS counters to count nested elements?
Yes, CSS counters can be used to count nested elements. The counter is incremented for each occurrence of the specified element, regardless of its position in the document tree. This can be useful for creating nested numbered lists or for counting elements in a complex document structure.
Can I use CSS counters to create a table of contents?
Yes, CSS counters can be used to create a table of contents. By incrementing a counter for each section or subsection in a document, you can create a numbered list that corresponds to the document structure. The ‘content’ property can then be used to display the counter value, creating a dynamic table of contents.
James is a freelance web developer based in the UK, specialising in JavaScript application development and building accessible websites. With more than a decade's professional experience, he is a published author, a frequent blogger and speaker, and an outspoken advocate of standards-based development.