Nested ordered lists with consecutive numbering in the form of 1, 1.1, 1.1.1, etc.? Can be done with the CSS-Counter properties, in some browsers (like Internet Explorer 7), however that is more work than in others.

How does it work?

CSS-Counter counting instances of specific elements or selectors. These properties are not limited to the list-elements – for example headline elements in form of ‘chapters’ are another possible scenario for this feature.
In combination with the pseudo-elements :before and :after you are able to create a complete new variant of listing. Compared with the few options you had before (the html start attribute) the CSS Counter are much more powerful. The HTML attribute (which is depricated anyway) had only affect on that specific element, nesting wasn’t working.
The following CSS properties define the CSS counter:

  • counter-reset: Resets one or more Counters (a counter is simply an arbitrary variable), optional you can set a specific value for resetting, the default ist 0.
  • counter-increment: Increases one or more counters, simular to counter-reset the second optional value affects the numbering. (by the way, even negative values are allowed).
  • counter: It would be useless if you can’t display the counters. Using the functions counter() or counters() in content property will display the numbering.

OL { 
	counter-reset: item; 
}
OL LI { 
	display: block;
}

OL LI:before { 
	content: counter(item) ". "; 
	counter-increment: item;
}

The result – just a “normal” ordered list, the only possibly advantage of this variant is that you can apply custom layout rules easier, without additional nesting of a list element content. Caveats at this point: In terms of “accessibility” this is bad, because CSS generated content is not available via the DOM (see CSS generated content techniques), so that in some screen readers this information will simply lack.
Anyway, let’s enhance the listing a bit more:


OL LI:before { 
	content: counters(item, ".") "."; 
	counter-increment: item;
}

Now we get a nested list. The function counters() in opposite to counter returns all instances of one counter, and the second parameter is the delimeter.

But be careful with this syntax. In Internet Explorer 7 this causes a real horrible bug – all the following CSS notations will not be interpreted, even if they are stored in separate stylesheet files. To be more precise – the notation of quotation marks inside the parentheses getting the IE CSS interpreter totally messed up.

The IE 7 Bug described occures only in a special combination of spaces and quotation marks (see this from Stackoverflow):


OL LI:before { 
	/* either add a whitespace on both sides */
	content: counters(item , ".") "."; 
	/* or remove all of them */
	content: counters(item,".") "."; 
	/* or use parentheses */
	content: counters('item',(".")) "."; 	
}

Jess Telford points out that the error only occurs when using delimiter with quotes.

For those who want to play a bit with this feature, I put together some examples, you find at Codepen.