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 likevalue
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 :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 :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 incounter-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: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 activatingclass
, 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 :<ol 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 :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…
No comments:
Post a Comment