CSS counters

CSS generated content allows for the insertion of a simple numbering system called counters. In its simplest form, CSS counters rely on the creation of scopes within the page element they're attached to. For example, let's say that we have a simple unordered list and we want to attach counters to it. Here's the markup:

<ul id="one">
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>

And here's our element's scope:

ul [SCOPE]
  1 li
  2 li
  3 li
/ul [/SCOPE]

In this case, our counters will work on a single scope. Here's the CSS code:

#one {

    counter-reset: one; /* creates the scope for the counter and initializes it */

}

#one li:before {

    counter-increment: one; /* increments the counter */
    content: counter(one) '. '; /* displays it */

}

As you can see, the counter one lives within the scope of our simple unordered list. I've first initialized it, then incremented it and finally inserted it just before the actual content of each list item. But what happens when we have multiple nested elements and we want that each element have its numbering system? In this case, multiple scopes will be created. For example, given the following markup:

<ul id="multiple">
<li>Item

<ul>
    <li>Item
        <ul>
        
            <li>Item</li>
        
        </ul>
    </li>
</ul>

</li>

<li>Item</li>

</ul>

we have this structure:

ul [SCOPE 1]

  1 li
  
    ul [SCOPE 2]
    
      1.1 li
      
        ul [SCOPE 3]
        
          1.1.1 li
          
        /ul [/SCOPE 3]
        
    /ul [/SCOPE 2]
    
  2 li
  
/ul [/SCOPE 1]

As you can see, each scope is contained within a parent scope. This reflects the progressive numbering showed in the diagram. To get the desired result, we have to concatenate each counter with its parent counter, like so:

#multiple {

    counter-reset: multiple;
    

}

#multiple li:before {

    counter-increment: multiple;
    content: counter(multiple) '. ';

}

#multiple li ul {

    counter-reset: multiple-a;

}

#multiple li ul li:before {

    counter-increment: multiple-a;
    content: counter(multiple) '. ' counter(multiple-a) ' ';

}

#multiple li ul li ul {

    counter-reset: multiple-b;
    


}

#multiple li ul li ul li:before {

    counter-increment: multiple-b;
    content: counter(multiple) '. ' counter(multiple-a) '. ' counter(multiple-b) ' ';

}

Each scope has its own counter which also inherits the counter from the parent scope. Here all the work is done by the content property that displays the counters in the desired order. You can see the results below.

This entry was posted in by Gabriele Romanato. Bookmark the permalink.

Leave a Reply

Note: Only a member of this blog may post a comment.