2.3 Class and ID Selectors

So far, we've been grouping selectors and declarations together in a variety of ways, but the selectors we've been using are still simple ones. The selectors we've used refer only to document elements; they're fine up to a point, but there are times when you need something a little more specialized.

In addition to raw document elements, there are two other types of selectors: class selectors and ID selectors, which let you assign styles in a way that is independent of document elements. These selectors can be used on their own or in conjunction with element selectors. However, they work only if you've marked up your document appropriately, so using them generally involves a little forethought and planning.

For example, say you're drafting a document that discusses ways of handling plutonium. The document contains various warnings about safely dealing with such a dangerous substance. You want each warning to appear in boldface text so that it will stand out. However, you don't know which elements these warnings will be. Some warnings could be entire paragraphs, while others could be a single item within a lengthy list or a small section of text. So, you can't define a rule using simple selectors of any kind. Suppose you tried this route:

p {font-weight: bold;}

All paragraphs would be bold, not just those that contain warnings. You need a way to select only the text that contains warnings, or more precisely, a way to select only those elements that are warnings. How do you do it? You apply styles to parts of the document that have been marked in a certain way, independent of the elements involved, by using class selectors.

2.3.1 Class Selectors

The most common way to apply styles without worrying about the elements involved is to use class selectors. Before you can use them, however, you need to modify your actual document markup so that the class selectors will work. Enter the class attribute:

<p >When handling plutonium, care must be taken to avoid the formation of a critical mass.</p> <p>With plutonium, <span >the possibility of implosion is very real, and must be avoided at all costs</span>. This can be accomplished by keeping the various masses separate.</p>

In order to associate the styles of a class selector with an element, you must assign a class attribute to the appropriate value. In the previous code, a class value of warning was assigned to two elements: the first paragraph and the span element in the second paragraph.

All you need now is a way to apply styles to these classed elements. In HTML documents, you can use a very compact notation where the name of a class is preceded by a period (.) and can be joined with a simple selector:

*.warning {font-weight: bold;}

When combined with the example markup shown earlier, this simple rule has the effect shown in Figure 2-7. That is, the style of font-weight: bold will be applied to every element (thanks to the presence of the universal selector) that carries a class attribute with a value of warning.

Figure 2-7. Using a class selector

As you can see, the class selector works by directly referencing a value that will be found in the class attribute of an element. This reference is always preceded by a period (.), which marks it as a class selector. The period helps keep the class selector separate from anything with which it might be combined like an element selector. For example, you may want boldface text only when an entire paragraph is a warning:

p.warning {font-weight: bold;}

The selector now matches any p elements that have a class attribute containing the word warning, but no other elements of any kind, classed or otherwise. The selector p.warning translates to: "Any paragraph whose class attribute contains the word warning." Since the span element is not a paragraph, the rule's selector doesn't match it, and it won't be converted to bold text.

If you did want to assign different styles to the span element, you could have used the selector span.warning:

p.warning {font-weight: bold;} span.warning {font-style: italic;}

In this case, the warning paragraph is boldfaced, while the warning span is italicized. Each rule applies only to a specific type of element/class combination and so does not leak over to other elements.

Another option is to use a combination of a general class selector and an element-specific class selector to make the styles even more useful, as in the following markup:

.warning {font-style: italic;} span.warning {font-weight: bold;}

The results are shown in Figure 2-8.

Figure 2-8. Using generic and specific selectors to combine styles

In this situation, any warning text will be italicized, but only the text within a span element and text with a class of warning will be boldfaced and italicized.

Notice the format of the general class selector in the previous example: it's simply a class name preceded by a period without any element name. In cases where you only want to select all elements that share a class name, you can omit the universal selector from a class selector without any ill effects.

2.3.2 Multiple Classes

In the previous section, we dealt with class values that contained a single word. In HTML, it's possible to have a space-separated list of words in a single class value. For example, if you want to mark a particular element as being both urgent and a warning, you could write:

<p >When handling plutonium, care must be taken to avoid the formation of a critical mass.</p> <p>With plutonium, <span >the possibility of implosion is very real, and must be avoided at all costs</span>. This can be accomplished by keeping the various masses separate.</p>

The order of the words doesn't actually matter; warning urgent would also suffice.

Now let's say you want all elements with a class of warning to be boldface, those with a class of urgent to be italic, and those elements with both values to have a silver background. This would be written as follows:

By chaining two class selectors together, you can select only those elements that have both class names, in any order. As you can see, the HTML source contains but the CSS selector is written .warning.urgent. Regardless, the rule will still cause the "When handling plutonium..." paragraph to have a silver background, as illustrated in Figure 2-9.

Figure 2-9. Selecting elements with multiple class names

If a multiple class selector contains a name that is not in the space-separated list, then the match will fail. Consider the following rule:

p.warning.help {background: red;}

As you would expect, the selector will match only those p elements with a class containing the words warning and help. Therefore, it will not match a p element with just the words warning and urgent in its class attribute. It would, however, match the following:

<p >Help me!</p>

Internet Explorer for both platforms has problems correctly handling multiple class selectors. While you can select a single class name out of a list, selecting based on multiple names in a list will not work properly. Thus, p.warning would work as expected, but p.warning.help would match any p elements that have a class attribute with the word help because it came last in the selector. If you wrote p.help.warning, then Explorer would match any p elements that have warning in their class value.

2.3.3 ID Selectors

In some ways, ID selectors are similar to class selectors, but there are a few crucial differences. First, ID selectors are preceded by an octothorpe (#) also known as a pound sign, hash mark, or tic-tac-toe board instead of a period. Thus, you might see a rule like this one:

*#first-para {font-weight: bold;}

This rule applies boldface text to any element whose id attribute has a value of first-para.

The second difference is that instead of referencing values of the class attribute, ID selectors refer, unsurprisingly, to values found in id attributes. Here's an example of an ID selector in action:

*#lead-para {font-weight: bold;} <p >This paragraph will be boldfaced.</p> <p>This paragraph will NOT be bold.</p>

Note that the value lead-para could have been assigned to any element within the document. In this particular case, it is applied to the first paragraph, but you could have applied it just as easily to the second or third paragraph.

As with class selectors, it is possible to omit the universal selector from an ID selector. In the previous example, you could also have written:

#lead-para {font-weight: bold;}

The effect of this selector would be the same.

2.3.4 Deciding Between Class and ID

You may assign classes to any number of elements, as demonstrated earlier; the class name warning was applied to both a p and a span element, and it could have been applied to many more elements. IDs, on the other hand, are used once, and only once, within an HTML document. Therefore, if you have an element with an id value of lead-para, no other element in that document can have an id value of lead-para.

In the real world, browsers don't usually check for the uniqueness of IDs in HTML, which means that if you sprinkle an HTML document with several elements, all of which have the same value for their ID attributes, you'll probably get the same styles applied to each. This is incorrect behavior, but it happens anyway. Having more than one of the same ID value in a document also makes DOM scripting more difficult, since functions like getElementById( ) depend on there being one, and only one, element with a given ID value.

Unlike class selectors, ID selectors can't be combined, since ID attributes do not permit a space-separated list of words.

On a purely syntactical level, the dot-class notation (e.g., .warning) is not guaranteed to work for XML documents. As of this writing, the dot-class notation works in HTML, SVG, and MathML, and it may well be permitted in future languages, but it's up to each language's specification to decide that. The hash-ID notation (e.g., #lead) will work in any document language that has an attribute that enforces uniqueness within a document. Uniqueness can be enforced with an attribute called id, or indeed anything else, as long as the attribute's contents are defined to be unique within the document.

Another difference between class and id names is that IDs carry a heavier weight when trying to determine which styles should be applied to a given element. I'll explain this in greater detail in the next chapter.

Like classes, IDs can also be selected independently of an element. There may be circumstances in which you know that a certain ID value will appear in a document, but you don't know the element on which it will appear (as in the plutonium-handling warnings), so you'll want to declare standalone ID selectors. For example, you may know that in any given document, there will be an element with an ID value of mostImportant. You don't know whether that most important thing will be a paragraph, a short phrase, a list item, or a section heading. You know only that it will exist in each document, occur in an arbitrary element, and appear no more than once. In that case, you would write a rule like this:

#mostImportant {color: red; background: yellow;}

This rule would match any of the following elements (which, as I noted before, should not appear together in the same document because they all have the same ID value):

Also note that class and ID selectors may be case-sensitive, depending on the document language. HTML and XHTML define class and ID values to be case-sensitive, so the capitalization of your class and ID values must match that found in your documents. Thus, in the following pairing of CSS and HTML, the element will not be boldfaced:

p.criticalInfo {font-weight: bold;} <p >Don't look down.</p>

Because of the change in case for the letter "I", the selector will not match the element shown.

Some older browsers did not treat class and ID names as case-sensitive, but all current browsers as of this writing enforce case sensitivity.