DekGenius.com
Previous Section  < Day Day Up >  Next Section

2.6 Pseudo-Classes and Pseudo-Elements

Things get really interesting with pseudo-class selectors and pseudo-element selectors. These selectors let you assign styles to structures that don't necessarily exist in the document, or to phantom classes that are inferred by the state of certain elements, or even by 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.

It may sound like I'm applying styles at random, but I'm not. Instead, I'm applying styles based on somewhat ephemeral conditions that can't be predicted in advance. However, the circumstances under which the styles will appear are, in fact, well-defined. Think of it this way: during a sporting event, whenever the home team scores, the crowd will cheer. You don't know exactly when during a game the scoring will happen, but when it does, the crowd will cheer, just as predicted. The fact that you can't predict the moment of the cause doesn't make the effect any less expected.

2.6.1 Pseudo-Class Selectors

Let's begin by examining pseudo-class selectors since they're better supported by browsers and are therefore more widely used.

Consider the anchor element (a), which, in HTML and XHTML, establishes 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 have yet to be visited. You can't tell the difference by simply looking at the HTML markup, because in the markup, all anchors look the same. The only way to tell which links have been visited is by comparing the links in a document to the user's browser history. So, there are actually two basic types of anchors: visited and unvisited. These types are known as pseudo-classes, and the selectors that use them are called pseudo-class selectors.

To better understand these classes and selectors, consider how browsers behave with regard to links. The Mosaic convention designated that links to pages you hadn't visited were blue, and links to already visited pages were red (the red became purple in succeeding browsers such as Internet Explorer). So, if you could insert classes into anchors, such that any anchor already 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>

However, such an approach requires that the classes on anchors change every time you visit 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":

a:visited {color: red;}

Now any anchor that points to a visited page will 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 -element keywords are preceded by a colon.

2.6.1.1 Link pseudo-classes

CSS2.1 defines two pseudo-classes that apply only to hyperlinks. In HTML and XHTML 1.0 and 1.1, these would be any a elements having an href attribute; in XML languages, they would be any elements that act as links to another resource. Table 2-1 describes these two pseudo-classes.

Table 2-1. Link pseudo-classes

Name

Description

:link

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

:visited

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

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? If that's the case, all we should need is the following:

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

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

<a name="section4">4. The Lives of Meerkats</a>

The resulting text would be blue because the a element will match the rule a {color: blue;}, as shown above. 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 */

As you may have already realized, the :link and :visited pseudo-class selectors are functionally equivalent to the body attributes link and vlink. Assume that an author wants all anchors to unvisited pages to be purple and anchors to visited pages to be silver. In HTML 3.2, this could be done as follows:

<body link="purple" vlink="silver">

In CSS, the same effect would be accomplished with:

a:link {color: purple;}
a:visited {color: silver;}

In the case of the CSS pseudo-classes, of course, you can apply more than just colors. Let's say you want visited links to be italicized and to have, in addition to their silver color, a strikethrough line, as shown in Figure 2-20.

Figure 2-20. Applying multiple styles to a visited link
figs/css2_0220.gif

This is simply done with the following styles:

a:visited {color: silver; text-decoration: line-through; font-style: italic;}

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

<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 rule will make the second anchor in the preceding markup maroon, while the first anchor will remain the default color for hyperlinks (usually blue).

The same general syntax is used for ID selectors as well:

a#footer-copyright:link{font-weight: bold;}
a#footer-copyright:visited {font-weight: normal;}

Although :link and :visited are very useful, they're also static—they typically don't change the styling of a document after its initial display. Other pseudo-classes that aren't quite so static are available in CSS2.1; we'll review them next.

2.6.1.2 Dynamic pseudo-classes

CSS2.1 defines three pseudo-classes that can change a document's appearance as a result of user behavior. These dynamic pseudo-classes have traditionally been used to style hyperlinks, but the possibilities are much wider. Table 2-2 describes these pseudo-classes.

Table 2-2. Dynamic pseudo-classes

Name

Description

:focus

Refers to any element that currently has the input focus—i.e., can accept keyboard input or be activated in some way.

:hover

Refers to any element over which the mouse pointer is placed—e.g., a hyperlink over which the mouse pointer is hovering.

:active

Refers to any element that has been activated by user input—e.g., a hyperlink on which a user is clicking during the time the mouse button is held down.

As with :link and :visited, these pseudo-classes are most familiar in the context of hyperlinks. Many web pages have styles that look like this:

a:link {color: navy;}
a:visited {color: gray;}
a:hover {color: red;}
a:active {color: yellow;}

The first two rules use link pseudo-classes, and the last two employ dynamic pseudo-classes. :active is analogous to the alink attribute in HTML 3.2, although, as before, you can apply color changes and any style you like to active links.

The order of the pseudo-classes is more important than it might seem at first. The usual recommendation is "link-visited-hover-active," although this has been modified to "link-visited-focus-hover-active." The next chapter explains why this particular ordering is important and reasons you might choose to change or even ignore the recommended ordering.


Notice that the dynamic pseudo-classes can be applied to any element, which is good since it's often useful to apply dynamic styles to elements that aren't links. For example, using this markup:

input:focus {background: silver; font-weight: bold;}

you could highlight a form element that is ready to accept keyboard input, as shown in Figure 2-21.

Figure 2-21. Highlighting a form element that has focus
figs/css2_0221.gif

You can also perform some rather odd feats by applying dynamic pseudo-classes to arbitrary elements. You might decide to give users a "highlight" effect by way of the following:

body *:hover {background: yellow;}

This rule will cause any element that's descended from the body element to acquire a yellow background when it's in a hover state. Headings, paragraphs, lists, tables, images, and anything else found inside the body will be changed to have a yellow background. You could also change the font, put a border around the element being hovered, or anything else the browser will let you do.

Internet Explorer for Windows through IE6, the most recent version as of this writing, does not permit dynamic pseudo-classes to select any elements other than hyperlinks.


2.6.1.3 Real-world issues with dynamic styling

Dynamic pseudo-classes raise some interesting issues and peculiarities. For example, it's possible to set visited and unvisited links to one font size and make hovered links a larger size, as shown in Figure 2-22:

a:link, a:visited {font-size: 13px;}
a:hover {font-size: 20px;}
Figure 2-22. Changing layout with dynamic pseudo-classes
figs/css2_0222.gif

As you can see, the user agent increases the size of the anchor while the mouse pointer hovers over it. A user agent that supports this behavior must redraw the document while an anchor is in hover state, which could force a reflow of all the content that follows the link.

However, the CSS specifications state that user agents are not required to redraw a document once it's been rendered for initial display, so you can't absolutely rely on your intended effect actually happening. I strongly recommend that you avoid designs that depend on such behavior.

2.6.1.4 Selecting a first child

Another static pseudo-class, :first-child, is used to select elements that are the first children of other elements. This particular pseudo-class is easily misunderstood, so an extended example is in order. Consider the following markup:

<div>
<p>These are the necessary steps:</p>
<ul>
<li>Insert key</li>
<li>Turn key <strong>clockwise</strong></li>
<li>Push accelerator</li>
</ul>
<p>
Do <em>not</em> push the brake at the same time as the accelerator.
</p>
</div>

In this example, the elements that are first children are the first p, the first li, and the strong and em elements. Given the following two rules:

p:first-child {font-weight: bold;}
li:first-child {text-transform: uppercase;}

you get the result shown in Figure 2-23.

Figure 2-23. Styling first children
figs/css2_0223.gif

The first rule boldfaces any p element that is the first child of another element. The second rule uppercases any li element that is the first child of another element (which, in HTML, must be either an ol or a ul element).

The most common error is to assume that a selector like p:first-child will select the first child of a p element. However, remember the nature of pseudo-classes, which is to attach a sort of phantom class to the element associated with the pseudo-class. If you were to add actual classes to the markup, it would look like this:

<div>
<p class="first-child">These are the necessary steps:</p>
<ul>
<li class="first-child">Insert key</li>
<li>Turn key <strong class="first-child">clockwise</strong></li>
<li>Push accelerator</li>
</ul>
<p>
Do <em class="first-child">not</em> push the brake at the same time as the accelerator.
</p>
</div>

Therefore, if you want to select those em elements that are the first children of another element, you write em:first-child. This selector allows you to, for example, style the first list item in a list, the first paragraph of a div, or the first td in a table row.

Internet Explorer for Windows through IE6, the most recent version as of this writing, does not support :first-child.


2.6.1.5 Selecting based on language

For situations where you want to select an element based on its language, you can use the :lang( ) pseudo-class. In terms of its matching patterns, the :lang( ) pseudo-class is exactly like the |= attribute selector. For example, to italicize any element in the French language, you would write:

*:lang(fr) {font-style: italic;}

The primary difference between the pseudo-selector and the attribute selector is that the language information can be derived from a number of sources, some of which are outside the element itself. As CSS2.1 states:

In HTML, the language is determined by a combination of the "lang" attribute, the META element, and possibly by information from the protocol (such as HTTP headers). XML uses an attribute called xml:lang, and there may be other document language-specific methods for determining the language.

Therefore, the pseudo-class is a bit more robust than the attribute selector and is probably a better choice in most cases where language-specific styling is needed.

2.6.1.6 Combining pseudo-classes

With CSS2.1, you can combine pseudo-classes in the same selector. For example, you can make unvisited links red when they're hovered, but visited links maroon:

a:link:hover {color: red;}
a:visited:hover {color: maroon;}

The order you specify doesn't actually matter; you could also write a:hover:link to the same effect. It's also possible to assign separate hover styles to unvisited and visited links that are in another language—for example, German:

a:link:hover:lang(de) {color: gray;}
a:visited:hover:lang(de) {color: silver;}

Be careful not to combine mutually exclusive pseudo-classes. For example, a link cannot be both visited and unvisited, so a:link:visited doesn't make any sense. User agents will most likely ignore such a selector and thus effectively ignore the entire rule.

Internet Explorer for Windows through IE6, which is the most recent version as of this writing, does not correctly recognize combined pseudo-classes. As with class-value combinations, it will pay attention to the last of the combined pseudo-classes. Thus, given a:link:hover, it will pay attention to the :hover but not the :link portion of the selector.


2.6.2 Pseudo-Element Selectors

Much as pseudo-classes assign phantom classes to anchors, pseudo-elements insert fictional elements into a document in order to achieve certain effects. Four pseudo-elements are defined in CSS2.1: styling the first letter, styling the first line, and styling before and after elements.

2.6.2.1 Styling the first letter

The first pseudo-element styles the first letter, and only that letter, of a block-level element:

p:first-letter {color: red;}

This rule causes the first letter of every paragraph to be colored red. Alternatively, you could make the first letter of each h2 twice as big as the rest of the heading:

h2:first-letter {font-size: 200%;}

The result of this rule is shown in Figure 2-24.

Figure 2-24. The :first-letter pseudo-element in action
figs/css2_0224.gif

As I mentioned, this rule effectively causes the user agent to respond to a fictional element that encloses the first letter of each h2. It would look something like this:

<h2><h2:first-letter>T</h2:first-letter>his is an h2 element</h2>

The :first-letter styles are applied only to the contents of the fictional element shown in the example. This <h2:first-letter> element does not appear in the document source. Instead, its existence is constructed on the fly by the user agent and is used to apply the :first-letter style(s) to the appropriate block of text. In other words, <h2:first-letter> is a pseudo-element. Remember, you don't have to add any new tags. The user agent will do it for you.

2.6.2.2 Styling the first line

Similarly, :first-line can be used to affect the first line of text in an element. For example, you could make the first line of each paragraph in a document purple:

p:first-line {color: purple;}

In Figure 2-25, 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 is. If the first line contains only the first five words of the paragraph, then only those five words will be purple. If the first line contains the first 30 words of the element, then all 30 will be purple.

Figure 2-25. The :first-line pseudo-element in action
figs/css2_0225.gif

Since the text from "This" to "only" should be purple, the user agent employs a fictional markup that looks something like this:

<p><p:first-line>This is a paragraph of text that has only</p:first-line>
one stylesheet applied to it. That style
causes the first line to be purple. No other ...

If the first line of text were edited to include only the first seven words of the paragraph, then the fictional </p:first-line> would move back and occur just after the word "that."

2.6.2.3 Restrictions on :first-letter and :first-line

In CSS2, the :first-letter and :first-line pseudo-elements can be applied only to block-level elements such as headings or paragraphs and not to inline-level elements such as hyperlinks. In CSS2.1, :first-letter applies to all elements. There are also limits on the CSS properties that may be applied to :first-line and :first-letter. Table 2-3 displays the limits.

Table 2-3. Properties permitted on pseudo-elements

:first-letter

:first-line

All font propertiesAll font properties
All color propertiesAll color properties
All background propertiesAll background properties
All margin propertiesword-spacing
All padding propertiesletter-spacing
All border propertiestext-decoration
text-decorationvertical-align
vertical-align (if float is set to none)text-transform
text-transformline-height
line-heightclear (CSS2 only; removed in CSS2.1)
floattext-shadow (CSS2 only)
letter-spacing (added in CSS2.1) 
word-spacing (added in CSS2.1 
clear (CSS2 only; removed in CSS2.1) 
text-shadow (CSS2 only) 

In addition, all pseudo-elements must be placed at the very end of the selector in which they appear. Therefore, it would not be legal to write p:first-line em since the pseudo-element comes before the subject of the selector (the subject is the last element listed). The same rule applies to the other two pseudo-elements CSS2.1 defines.

2.6.2.4 Style before and after elements

Let's say you want to preface every h2 element with a pair of silver square brackets as a typographical effect:

h2:before {content: "]]"; color: silver;}

CSS2.1 lets you insert generated content, and then style it directly using the pseudo-elements :before and :after. An example is shown in Figure 2-26.

Figure 2-26. Inserting content before an element
figs/css2_0226.gif

The pseudo-element is used to insert the generated content and to style it. To place content after an element, use the pseudo-element :after. You could end your documents with an appropriate finish:

body:after {content: "  The End.";}

Generated content is a separate subject, and the entire topic (including more detail on :before and :after) is covered in more detail in Chapter 12.

    Previous Section  < Day Day Up >  Next Section