CSS content, counter-increment & counter-reset

I have never used the counter or increment properties since they aren’t supported in IE7 or earlier, nor are the :before pseudo elements, or content property. Since IE8 does support all of these, soon we may be able to include these CSS properties, so I thought I would explain them.

The <ol> start attribute and <li> value element were deprecated in HTML 4.01 and not supported in XHTML strict. The value attribute set the number of a list item, enabling the following list items to increment from that value. While there is no (X)HTML replacement for these elements, CSS 2.1 provides methods for setting and incrementing counters on any element, not just <li>’s. This article focuses on the following CSS pseudo elements and properties:

content CSS property

:before pseudo-element

:after pseudo-element

counter-increment CSS property

counter-reset CSS property

The content property is used in conjunction with the :before or :after pseudo-elements. The value of the content property is added to the visual layout of your document, but is NOT added to the DOM. If you’re reading this tutorial, you should already know that! We’re discussing :before, :after and content here because without them, the counter is kind of useless: if you’re not going to display the content of a counter before (or perhaps after) an element, why include it?

Overview of content property

To make understanding this tutorial easier, we are going to use the concrete example of adding ” – <hrefValue>” after every link, which is helpful when using print CSS.

Listing 3: Here we’ve defined the color and font-style for the generated content.

While the generated content is NOT added to the DOM, think of it as an added span that inherits everything from it’s parent. The content cannot contain any HTML, just ASCII, escaped and ISO characters. As mentioned, content is used with the :before and :after pseudo-elements to generate content in a document.

normal: Computes to ‘none’ for the :before and :after pseudo-elements unless the default browser rendering includes content (i.e. <q>) which is handled differently based on the browser – Safari shows the default content, IE8 and FF do not.

content: "Estelle: ";content: "\00a3 "; /* includes 'Â£' */

string: Adds a string before or after the element (depending on which pseudo-element is used). Strings can either be written with double or single quotes. If your string includes a quotation mark, make sure you escape it with a slash-quote or slash-ISO value. If you are going to include any non-ASCII characters or entities, declare the charset in your CSS and XHTML, and/or use the ISO code for the character. Check out my blog post on including named entities in CSS and Javascript

content: url(myBullet.gif);

url: The value is a URI that designates an external resource (such as an image). If the browser can’t display the resource, FF and IE8 omit it, as if it were not specified, but Safari indicates that the resource cannot be displayed with a missing image icon.

content: open-quote;

open-quote and close-quote: These values are replaced by the appropriate string from the ‘quotes’ property. Opera handles this, but does not nest quotes correctly, Safari ignores this completely. IE8 and Firefox get it right.

content: open-quote;

no-open-quote and no-close-quote: Introduces no content, but increments (decrements) the level of nesting for quotes. Safari ignores this completely. Opera, IE8 and Firefox get it right.

content: attr(title);

attr(x): This function returns as a string the value of attribute X for the subject of the selector. The string is not parsed by the CSS processor. If the subject of the selector doesn’t have an attribute X, an empty string is returned. The case-sensitivity of attribute names depends on the document language.

For uber coolness, or geekiness as the case may be, you can add text dynamically without using javascript.

counter(name) or counter(name, style): The counter takes two parameters: the name, which you can reference to increment or reset, and the style, which, if not declared, defaults to “decimal”. While you can name the counter almost anything except ‘none’, ‘inherit’ or ‘initial’, avoid key terms.

Browser support for the CSS content property and :before and :after pseudo elements

The CSS content property and possible values

IE6

IE7

IE7 in IE8

IE8

FF3

FF 3.5 Beta

Saf 3.2

Saf 4 Beta

Opera 9.64

:before

:after

content

Since :before and :after is not supported in these browsers, testing is not possible, and moot. It is assumed that IE6 and IE7 does not support the content property, therefore supports none of these values

works, except for issues below

works, except for issues below

works, except for issues below

none

n

normal

displays quotes on <q> Makes sense, but not the spec.

url()

nothing

nothing

nothing

missing image icon

missing image icon

missing image alt

string

open-quote
close-quote

Does not nest quotes correctly, but does include quotes.

no-open-quoteno-close-quote

attr(x)

counter

counter-increment and counter-reset CSS properties

Counters don’t work on their own! if you just write p:before {content: counter(subtitles, decimal);} every paragraph will have a zero in front of it. To more easily understand this, let’s think of real world examples:

footnotes

creating numbering for outlines: counting chapters, sections and subsections, restarting the subsection counter for each new section, and resetting the section counter for each new chapter

Using the CSS counter syntax you can define as many counters as you like in your page, increment the counters and reset the counters. While the counter gets physically added to the presentation of the page (not the DOM) using the CSS counter value on the content property as a pseudo element using the :before or :after syntax, the increment happens on an actual element on the page.

<p> With this paragraph, I have included <cite class="footnote">citation to footnote</cite>.</p>
cite.footnote {counter-increment: citations;}
cite.footnote:after {content: counter(citations); vertical-align:text-top;}

In our example above, we would increment the counter on every <cite class="footnote">, then add the footnote numbers using the content property on the :after pseudo element. In order to use a counter, you should give it a name. In the above scenario, the name is “citations”. You can also specify the style. If the style is not declared, the style defaults to decimal. The values include all the list-style-type values, though only <ol> values make sense with a counter. Values include decimal | decimal-leading-zero | lower-alpha | lower-greek | lower-roman | upper-alpha | upper-roman | lower-latin | upper-latin | hebrew | georgian and others.

You can include more than one counter in generated content. For example, in legalese, you often have sections within sections all numbered. This is doable with CSS counters.

Now all <h2>s are preceded by their header number and subsection number.

A few things to note about the code: note that in the h2:before declaration we’ve included two counters: the header counter and the subsection counter. We declared the style in both calls, as style is NOT inherited. Also, we’ve included strings within our declaration. Note that there are quotes delimiting our strings, but not our counters, and there are no concatenation elements without our content value. To combine multiple counter ID’s in the same style attribute, string them together using space delimited counter ID values.

Incrementing of the counter was done through the counter-increment declaration. While the default value is to increment by 1, we can increment by other values. You can also reset counters. It makes sense to reset subsections after every header. To overwrite the default value of 1, and to reset after each <h1> the CSS could be:

12 Responses to CSS content, counter-increment & counter-reset

Iâ€™m not quite sure what you mean when you state, â€œThe <ol> start attribute and <li> value element were deprecated in HTML 4.01 and not supported in XHTML strict.â€ <ol> is an element rather than an attribute, â€œstart attributeâ€ is nonsensical, and both <ol> and <li> elements are supported not only in HTML 4.01 and XHTML 1.0 strict but in the W3Câ€™s XHTML 1.1 and XHTML Modularization 1.1 recommendations.

Thanks for the useful citation example. I had to modify it slightly so that the citation number would continue incrementing across many more paragraphs (the example above meant it would revert to 1 for the first citation in a new paragraph).

CSS has crossed the line and is way deep into HTML private field of responsibility and ‘property’.
CSS should not be allowed to: render; serve; or by any other means, generate contents not contained in HTML.

CSS working team must be ‘warned’ about this ‘violation’ and should be once again reminded of its own definition of that:
its sole purpose, responsibility and duty – is to generate presentational STYLE of the web-CONTENT and make not a single step outside of its own field of responsibility. Because we all know that: semantically correct content-delivery mechanism is HTML fundamental responsibility by definition and the very reason it first came to existence.

CSS kids of W3C joint were also arguing about elements such as and similar to be obsolete, unnecessary, lacking semantic meaning and for being simply presentational – but that’s something to be expected from the mouth of an illiterate. Since a bold phrase in the middle of some plain meaningful content is purely semantic, and also a structural part of that content.

We all know and they should know that by order: 1.Content; 2.Content Semantics; and 3.Content Structure, belong solely to HTML.

On the other hand XHTML (saw it in the title) has nothing to do with any of theseâ€¦
– XHML is simply not HTML!
Its main concern was structure (bones), skeleton delivery and never gave a damn about content delivery. Those who grew up eating bones, love xhtml -but clients want content to feed their intellectual needs. But to xml this concern was of a third hand importance. Or to be more precise, of no importance at all.

Their primary concern was data-structure [omiting the data part] structure; that is, ‘bones’: -are they properly shaped? If not: The ‘flesh’ is no good – Return it!
We don’t need empty present boxes. We need Information. So why don’t you change that xhtml part of title into something userful, that is: HTML?