start page | rating of books | rating of authors | reviews | copyrights

Book HomeCascading Style Sheets: The Definitive GuideSearch this book

2.4. Pseudo-Classes and Pseudo-Elements

Even more interesting, at least in terms of syntax, are the pseudo-class and pseudo-element selectors. These allow the author to assign styles to structures that don't necessarily exist in the document, or to things that are inferred by the state of certain elements, or even the state of the document itself. In other words, the styles are applied to pieces of a document based on something other than the structure of the document, and in a way that cannot be precisely deduced simply by studying the document's markup.

This may sound like we're applying styles at random. Not at all! Instead, the styles are applied based on somewhat ephemeral conditions that can't be predicted in advance. Nonetheless, the circumstances under which the styles will appear are well-defined. This is sort of like saying, "During a sporting event, whenever the home team scores, the crowd will cheer." You don't know exactly when during a game this will happen, but when the right conditions occur, the crowd will do just as predicted. The fact that you can't predict the exact second (or inning, or quarter) in which this will happen doesn't make the behavior any less expected whenever the home team does score.

2.4.1. Pseudo-Class Selectors

First we'll look at pseudo-class selectors, since they're better supported by browsers and therefore more widely used. Let's use an example to see how they work; this will take a minute before I reach the actual point, so bear with me.

Consider the anchor, which is used to set up a link from one document to another. Anchors are always anchors, of course, but some anchors refer to pages that have already been visited, while others refer to pages that haven't been visited yet. You can't tell which are which by simply looking at the HTML markup, because in the markup, all anchors look the same. Only by comparing the links in a document to the user's browser history is it possible to tell which links have been visited and which have not. So, in a certain sense, there are two basic types of anchors: visited and unvisited. In fact, these types are known as pseudo-classes, and the selectors that use them are called pseudo-class selectors. These cause, in a certain sense, ghostly classes to be applied to elements.

To see what I mean, let's consider for a moment how browsers behave with regard to links. The Mosaic convention was that links to pages you hadn't visited were blue, and links to already visited pages were red (this was modified to purple in succeeding browsers such as Internet Explorer). If you could only insert classes into anchors, such that any anchor you had visited would have a class of, say, "visited," then you could write a style to make such anchors red:

A.visited {color: red;}

<A HREF="http://www.w3.org/" CLASS="visited">W3C Web site</A>

Such an approach, however, would require that the classes on anchors change every time you visited a new page, which is a little silly. Instead, CSS defines pseudo-classes that make the anchors to visited pages act as though they have classes of "visited." Thus:

A:visited {color: red;}

There you have it -- any anchor that points to a visited page will now be red, and you don't even have to add CLASS attributes to any of the anchors. Note the colon (:) in the rule. The colon separating the A and the visited is the calling card of a pseudo-class or pseudo-element. All pseudo-class and pseudo-element keywords are preceded by a colon.

Here's another example:

A:visited {color: silver;}

<A HREF="http://www.w3.org/">W3C Web site</A><BR>
<A HREF="http://www.nowhere.net/">Nowhere in particular</A>

As you can guess from Figure 2-13, the first anchor points to an already visited page, and so it's silver, whereas the second anchor is still blue, since the browser hasn't loaded that page before.

Figure 2-13

Figure 2-13. Pseudo-classes in action

In CSS1, there are only three pseudo-classes. We've already seen :visited , and in addition, there are :link and :active. Each refers to a different kind of anchor, as shown in Table 2-1.

Table 2-1. Psuedo-classes

Name

Description

:link

Refers to any anchor that is a hyperlink (i.e., has an HREF attribute) and that points to an address that has not been visited. Note that some browsers may interpret :link to refer to any hyperlink, visited or unvisited.

:visited

Refers to any anchor that is a hyperlink to an already visited page.

:active

Refers to any anchor that is in the process of being activated (e.g., clicked). In CSS1, this applies only to hyperlinks, whereas in CSS2, :active can theoretically apply to any element.

The first of the pseudo-classes in Table 2-1 may seem a little bit redundant. After all, if an anchor hasn't been visited, then it must be unvisited, right? Therefore, all we should need is the following:

A {color: blue;}
A:visited {color: red;}

That seems reasonable, but actually it's not quite enough. The first of the rules shown here will apply not only to unvisited links, but also target anchors such as this one:

<A NAME="section4">4. The Lives of Salmon</A>

The text shown would be blue, because the A element will match the first rule shown before. Therefore, in order to avoid applying your link styles to target anchors, use the :link pseudo-class:

A:link {color: blue;}    /* unvisited links are blue */
A:visited {color: red;}   /* visited links are red */
A:active {color: yellow;}  /* anchors turn yellow while clicked */

As you may have already realized, the :link , :visited , and :active selectors are functionally equivalent to the BODY attributes LINK , VLINK , and ALINK . In the case of the CSS pseudo-classes, of course, you can apply more than just colors.

Assume that an author wishes to create a page in which all anchors are purple if the linked pages haven't been visited, red if they have been, and yellow as the user clicks them. In HTML, this could be done as follows:

<BODY LINK="purple" VLINK="red" ALINK="yellow">

In CSS, this would be accomplished as:

A:link {color: purple;}
A:visited {color: red;}
A:active {color: yellow;}

This is a good place to bring class selectors back in and show how they can be combined with pseudo-classes. For example, let's say you wish to change the color of any link that points outside your own site. If you assign a class to each of these anchors, it's easy. For example:

<A HREF="http://www.mysite.net/">My home page</A>
<A HREF="http://www.site.net/" CLASS="external">Another home page</A>

In order to apply different styles to the external link, all you need is a rule like this:

A.external:link, A.external:visited {color: maroon;}

This will have the effect of setting the second anchor in the preceding markup to be maroon, while the first will be the default color for hyperlinks (usually blue).

2.4.1.1. Real-world issues

There are some interesting issues with the anchor pseudo-classes. For example, it would be possible to set visited and unvisited links to one font size, and active links to have a larger size:

A:link, A:visited {font-size: 12pt;}
A:active {font-size: 18pt;}

As you can see in Figure 2-14, the user agent has increased the size of the anchor as it's being clicked. A user agent that supports this behavior is forced to redraw the document as an anchor is being clicked. However, the CSS specifications specifically state the user agents are not required to do redraw a document once it's been drawn for initial display, so you can't absolutely rely on this happening. Whatever you do, avoid designs that depend on such behavior!

Figure 2-14

Figure 2-14. Resizing elements based on their state

WARNING

The :active pseudo-class isn't supported in Navigator 4.x or Opera 3.x, although it is supported in Explorer 4.x and 5.x.

2.4.2. Pseudo-Element Selectors

In a fashion similar to the way that pseudo-classes cause ghostly classes to be assigned to anchors, pseudo-elements trigger the insertion of fictional elements into a document in order to achieve certain effects.

In CSS1, there are two pseudo-elements, called :first-letter and :first-line. These are used to apply styles to the first letter or first line, respectively, of a block-level element such as a paragraph. For example:

P:first-letter {color: red;}

This will cause the first letter of every paragraph to be colored red, which is pretty straightforward. Another possibility is to make the first letter of each H2 twice as big as the rest of the heading, with the result seen in Figure 2-15:

H2:first-letter {font-size: 200%;}
Figure 2-15

Figure 2-15. The :first-letter pseudo-element in action

In a like way, :first-line can be used to affect the first line of text in an element. For example, we could make the first line of each paragraph in a document gray:

P:first-line {color: gray;}

In Figure 2-16, we see the style is applied to the first displayed line of text in each paragraph. This is true no matter how wide or narrow the display region may be. If the first line contains only the first five words of the paragraph, then only those five words will be gray. If the first line contains the first 30 words, then all 30 will be gray.

Figure 2-16

Figure 2-16. The :first-line pseudo-element in action

The reason :first-line and :first-letter are referred to as pseudo-element selectors is that they cause, in effect, a temporary element to appear within the document structure. This is most easily visualized with an example employing "fictional tags," as the CSS1 specification calls them.

Assume the following markup:

P:first-line {color: gray;}

<P>This is a paragraph of text which has only one style applied to it. That
style causes the first line to be gray. No other text in the paragraph is
affected by this rule (at least, it shouldn't be).</P>

Assume further that a user agent displays the text like this:

This is a paragraph of text which has only
one style applied to it. That style causes
the first line to be gray. No other ...

and so forth. Since the text from "This" to "only" should be gray, the user agent employs a fictional markup that looks something like this:

<P><P:first-line>This is a paragraph of text which has only</P:first-line>
one style applied to it. That style causes the first line to be gray. No other ...

This fictional tag sequence causes the effect seen in Figure 2-17.

Figure 2-17

Figure 2-17. How the pseudo-element selector :first-line works, in a theoretical sense

This <P:first-line> element does not appear in the document source. It isn't even a valid element at all. Instead, its existence is constructed on the fly by the user agent and used to apply the :first-line style(s) to the appropriate block of text. In other words, <P:first-line> is an element that isn't really an element, but is instead a pseudo-element. Remember, you don't have to add any new tags. The user agent will do it for you.

The :first-letter pseudo-element causes something similar to happen:

P:first-letter {font-weight: bold;}

<P><P:first-letter>T</P:first-letter>his is a paragraph of text which has
another style sheet applied to it. This time it uses a first-letter effect.

2.4.3. Restrictions on Pseudo-Class and Pseudo-Element Selectors

There are limits to the CSS properties that may be applied to :first-line and :first-letter. These are given in Table 2-2.

Table 2-2. Properties Permitted on Psuedo-elements

:first-letter

:first-line

all font properties

all color and background properties

text-decoration

vertical-align (if float is set to none)

text-transform

line-height

all margin properties

all padding properties

all border properties

float

clear

all font properties

all color and background properties

word-spacing

letter-spacing

text-decoration

vertical-align

text-transform

line-height

clear

Under CSS1, pseudo-classes and pseudo-elements cannot be combined within a single selector. As we will see, this changes to some degree in CSS2. It is possible to combine pseudo-class and -element selectors with class and ID selectors, although the syntax for doing so is fairly rigid. The pseudo-class or pseudo-element is always the very last thing in the selector, coming after the element, class, and/or ID portions of the selector :

A.external:link {color: gray;}
A#link721:visited {color: purple;}


Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.