Westciv Logo

These materials are copyright Western Civilisation Pty Ltd.

www.westciv.com

They are brought to you courtesy of Style Master CSS Editor and Westciv's standards based web development courses.

Please see our website for detailed copyright information or contact us info@westciv.com.

complete css guide

Generated content

If you cast your mind back you might recall our golden style sheets rule, separate appearance from content. Now, suddenly we are talking about generated content. You might be thinking, doesn't this introduce content into our style sheets? What about the golden rule? Well, it's a good question, and this area is one of controversy among style sheets experts. I won't buy into that debate here, but I want to cover the issue of generated content in CSS2 in this section.

Firstly, note that some kinds of generated content already exist in CSS1. Think about bulleted and numbered lists. These add numbering or bullets, so they do generate content to an extent. CSS2 adds more powerful ways of generating content. Here we learn how.

There are two aspects to generating content with CSS2.

Where is the content to be inserted?

To answer this question we use the two new CSS2 pseudo classes we saw a little earlier. The :before and :after pseudo classes are appended to selectors, and allow the insertion of generated content before or after selected elements. For example, you might want to put something before all headings of level 1. The pseudo element selector to do this is h1:before.

What content is to be inserted?

To do this we use a new property, content.

The content property allows us to define the content that is to be inserted before or after selected elements. Content can comprise

Let's take a look at the content property itself in detail, then we'll look at each of these different types of content as well.

content

What it does

The content property specifies the content to be added before or after an element selected by the :before and :after pseudo classes. It can only be used with these selectors.

Possible values

As mentioned above content can comprise a list of

Let's look at each of these values in turn.

Strings of text
Browser support

Get browser support information for strings of text as generated content in the downloadable version of this guide or our browser support tables.

What it does

Surprisingly, using this value will insert a string of text before or after the selected element.

Syntax

Say we wanted to generate the content "Chapter " before every heading level 1.

h1:before

{content: "Chapter "}

All you need do then is place the string of text you want to be generated between double quote marks.

counter and counters
What it does

counter values are more than a little involved. Think of them as super-charged versions of numbered lists. Counters have a name, and a style. You create a counter using the counter function, then use them in conjunction with the content property to insert markers into a document. This isn't quite as confusing as it initially seems.

There are two forms of the counter function, the counter form and the counters form.

The counter function has the form counter(identifier, list-style). The identifier is the name of the counter whose value you want to insert, while the (optional) list-style specifies what style of counter you want (for instance lower-roman.) These styles are the same as those for elements of type list-style. When the browser encounters a counter function, it determines the value of that counter at this point of the document, then inserts it into the document in the nominated style. How does it determine this value? See the section on the counter property below for more detail and examples.

The counters form is very similar, but allows for multiple counters to be inserted simultaneously. The form is counters(identifier, string, list-style). This returns all counters with the name specified by the identifier at this point of the document in the given list style, separated by the string. For more on this rather sophisticated aspect of CSS2, with examples, see the counters property below.

Keyword defined elements
Browser support

Get browser support information for keyword defined generated content in the downloadable version of this guide or our browser support tables.

What it does

At the moment, keyword values are limited to allowing the insertion of various types of quote marks.

Basically it works like this. You use the content property with a keyword value to define, for example, that there should be an opening quote before a certain element. You then use the quotes property to define what type of quote marks you want to appear. If you don't define a value for the quotes property, the default is up to the user agent. This means that it may put in some sort of quote mark just because you have given content the value of open-quote, but it may not be exactly what you have in mind.

The attr() function
Browser support

Get browser support information for the attr() function in the downloadable version of this guide or our browser support tables.

What it does

The last possible value for content, and unique to the content property is the attr() function. This returns the value of a named attribute of the selected element. The returned value is then inserted as a string. For example, with a link, the title of the link could be inserted after the link in the following way.

a:after {

content: attr(title)

}

This might be used in conjunction with an @media rule to specify that only when printing a page, the URL should be inserted after the link.

@media print

{a:after{

content: attr(href)

}

}

How is content added?

Now, after that long diversion, where we looked at the possible values that the content property can take, let's go back to just a couple more things about the content property itself.

Content is added as inline, block or marker elements. However the statement that creates the content can set the display of the content to be a block, or other kind of element, rather than an inline element. For example

body:after {

content: "The End";

display: block;

margin-top: 2em;

text-align: center;

}

places the text string "The End" at the foot of the page as a block, rather than as an inline element.

Default values

If no content is specified, the default value is an empty string.

Is it inherited?

An element does not inherit the content property of the element which contains it.

quotes

Browser support

Get browser support information for quotes in the downloadable version of this guide or our browser support tables.

What it does

The actual quotation marks that will be drawn are defined by the new quotes property. This property allows different quotation marks to be created for different elements (for example when quoting different languages the correct quotation marks for that language will be inserted automatically.)

The quotes property specifies the quote marks to be used for different levels of quotation. It is used in conjunction with a keyword value for the content property we saw above. When content takes a value of open-quote and close-quote, the open and close quotes inserted are those defined by the quotes property.

Possible values

quotes are defined as a list of pairs of strings. Each pair defines respectively the opening and the closing quotation mark. The pairs are separated by spaces, as is each element of a pair. For example the following statements create different quotes for different languages, including what should happen when quotes are nested.

/* Specify pairs of quotes for two levels in two languages */

q:lang(en) { quotes: '"' '"' "'" "'" }

q:lang(fr) { quotes: "«" "»" "<" ">" }

In English, according to this statement, first level quotes are double quoted, while second level quotes are single quoted. In French, first level quotes use "«" and "»" while second level quotes use "<" and ">".

Default values

If no value for quotes is specified, the default value is determined by the browser.

Is it inherited?

An element inherits the quotes property of the element which contains it.

Counters and counter properties

counter

Browser support

Get browser support information for counter in the downloadable version of this guide or our browser support tables.

Counters are sophisticated and powerful, and not surprisingly more than a little complex. But be not afraid, a little thinking and they are manageable. Here's how they work.

Counters are used exclusively by the content property to insert numbering (e.g. "1.5") before or after an element. You don't need to "create" a counter, just by referring to them they come into existence. For instance, let's suppose you created the simple rule below

h1:before {content: counter(chapter)}

This tells the browser to add the value of the counter called "chapter" before every heading of level one. But what value is that? Well, if we don't set the value using the properties we will discuss in a minute, the counter value will be 0. So every heading of level one will be preceded by a 0. We don't really want that. We want something along the lines of the first heading to be preceded by a 1, the second by a 2, and so on. To do this, we use the counter-increment property. This increments the value of a counter by a given value (you can jump up by 2, down by 1 (using the value of -1), as well as simply incrementing by one.)

To use counter-increment, name the counter you want to increment using the identifier for the counter, and then the value you want to increment by. (Again, simply using the property "creates" a counter with that identifier if it doesn't already exist). In the following example, we increment the value of the counter with an identifier "chapter" for each <h1> element.

h1 {counter-increment: chapter 1}

You can of course combine the two rules into this simple rule

h1:before {content: counter(chapter);

counter-increment: chapter 1

}

This increments the counter then adds it before the <h1> element. Note the special case that if you increment and use a counter in the same rule, it is incremented before being inserted even if the content property comes before the increment property.

What does this let us achieve? Well, now, instead of marking up the headings of each chapter in our HTML based document like this

<h1>1. Abstract</h1>

...

<h1>2. Introduction</h2>

We leave out the numbering and it is done automatically. This aids the editing and writing processes, because moving sections, subsections and so on, or deleting them, or inserting new sections doesn't necessitate re-entering every number! It's particularly useful where a document might be served up in pieces based on the user's needs, or the medium they are using.

Let's look at a more complex example, using subsections. Here we will also take a look at the counter-reset property. Any nontrivial piece of documentation will almost certainly be divided into sections and subsections. We've seen how to number the top level sections (we called them chapters), but what about subsections? The particular problem is resetting the counter at the beginning of a new subsection.

Here is what we do

h1:before {content: counter(chapter);

counter-increment: chapter 1

/* this is the same as the example above */

counter-reset: subsection 0

}

In this example, we reset the counter called subsection to 0 each time we start a new section (assuming the h1 is the start of a new section). Now we need to increment the subsection counter for each subsection (heading of level 2), then insert the subsection content so that our subsections are correctly numbered. Let's take a look.

h2:before {content: counter(chapter) "." counter(subsection);

counter-increment: subsection 1

}

This increments the counter called subsection, then inserts numbering of the form "2.5" before the text of the heading.

counters

Browser support

Get browser support information for counters in the downloadable version of this guide or our browser support tables.

The last thing we need to learn about counters is a little more involved again. Think about lists in HTML. These can contain other lists, which can contain others, and so on ad infinitum. It's not possible in advance to know how many levels there will be, so how do we take care of this situation? Fortunately those smart people at the W3C thought of this, and provide a solution. It's a little tricky, but not rocket science. Counters have a particular "scope". When a counter is created its scope is the level at which it was created, and all that level's children. However, where a counter of the same name is created inside the scope of the initial counter, then this is treated as a separate counter, which now takes over the counting. Confusing? Let's take a look at an example, taken from the CSS2 specification.

Here's the style sheet rule that creates the counter


ol { counter-reset: item }
li { display: block }
li:before { content: counter(item) ". "; counter-increment: item }

And here is the HTML


<ol>                 <!-- (set item[0] to 0          -->
    <li>item         <!--  increment item[0] (= 1)   -->
    <li>item         <!--  increment item[0] (= 2)   -->
      <ol>           <!--  (set item[1] to 0         -->
        <li>item     <!--   increment item[1] (= 1)  -->
        <li>item     <!--   increment item[1] (= 2)  -->
        <li>item     <!--   increment item[1] (= 3)  -->
          <ol>       <!--   (set item[2] to 0        -->
            <li>item <!--    increment item[2] (= 1) -->
          </ol>      <!--   )                        -->
          <ol>       <!--   (set item[3] to 0        -->
            <li>     <!--    increment item[3] (= 1) -->
          </ol>      <!--   )                        -->
        <li>item     <!--   increment item[1] (= 4)  -->
      </ol>          <!--  )                         -->
    <li>item         <!--  increment item[0] (= 3)   -->
    <li>item         <!--  increment item[0] (= 4)   -->
  </ol>              <!-- )                          -->
  <ol>               <!-- (reset item[4] to 0        -->
    <li>item         <!--  increment item[4] (= 1)   -->
    <li>item         <!--  increment item[4] (= 2)   -->

  </ol>              <!-- )                          -->

Each <ol> "creates" a counter called "item". Every list item inside the <ol> increments the counter, then inserts the number before itself. However, when we get to an <ol> inside another, a new counter called "item" is created. The other ones don't go away, they simply remain unchanged until their scope is again relevant. Note that they all have the same name. You might think this is a recipe for disaster, but there is a good reason for this.

Here's one last string to the counters and content bow. Imagine you want to insert the "full" number for every list item (for example 2.5.1). With the counter function you can only insert the value for one named counter. In this case it would be the value for the counter named item at the level you are currently at. How do we get all of the counters with that name which are relevant at the level we are at? With the counters function. We saw this in the section on content above, but let's revisit it. It has the form counters(identifier, string, list-style), (where the list-style is optional) and it does exactly what we want. It returns every counter in the document relevant at the point it is called, separated by the string you give, in the style specified. What do I mean by "relevant at this point?" Remember that the scope of a counter is inside the element in which it is created, including all of its children. Basically, a counter is relevant inside any of the children of the element which created it.

To cut a long story short, it's as simple as counters(item, ".")

counter-reset

Browser support

Get browser support information for counter-reset in the downloadable version of this guide or our browser support tables.

What it does

The counter-reset property sets the value of a named counter.

Possible values

counter-reset takes the name of the counter to reset. Counter names are identifiers, and comprise letters, numerals and hyphens. They cannot, however, begin with numerals or hyphens. It also takes an optional integer, to which it sets the value of the identified counter.

counter-reset can also take a list of identifiers and optional integers, to set the value of several counters simultaneously. This is no mere luxury. Because of cascading, the following will set only the counter named counter2.

h1 { counter-reset: counter1 -1 }

h1 { counter-reset: counter2 99 }

In order to reset both, the following must be used.

h1 { counter-reset: counter1 -1 counter2 99 }

counter-reset can also be set to none.

Default values

If no counter-reset is specified, the default value is none.

Is it inherited?

An element does not inherit the counter-reset property of the element which contains it.

counter-increment

Browser support

Get browser support information for counter-increment in the downloadable version of this guide or our browser support tables.

What it does

The counter-increment property increments the value of a named counter by a certain amount.

Possible values

counter-increment takes the name of the counter to increment. Counter names are identifiers, and comprise letters, numerals and hyphens. They cannot, however, begin with numerals or hyphens. It also takes an optional integer, by which it increments the value of the identified counter. If no integer is specified, the counter is incremented by one.

counter-increment can also take a list of identifiers and optional integers, to set the value of several counters simultaneously. This is no mere luxury. Because of cascading, the following will set only the counter named counter2.

h1 { counter-increment: counter1 -1 }

h1 { counter-increment: counter2 99 }

In order to reset both, the following must be used.

h1 { counter-increment: counter1 -1 counter2 99 }

counter-increment can also be set to none.

Default values

If no counter-increment is specified, the default value is none.

Is it inherited?

An element does not inherit the counter-increment property of the element which contains it.

Web Directions Conference
Style Master CSS Editor