Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Attribute Selectors Part II


WebReview.com: Attribute Selectors Part II

Attribute selectors are a fascinating new addition to CSS. As we saw last time, you can use them to apply styles to elements based on the presence of a certain attribute, or based on the specific value of a given attribute. That's already a lot of power, but it's just the beginning. As we'll see in this installment, you can start applying styles based on one of a number of attribute values, or even fragments of some types of values.

Picking from a List

Many authors don't realize this, but it is possible to have more than one value in a single class attribute. For example:

<p class="urgent warning">...</p>

Instead of being just one value, this can be seen as the joining of two distinct values: urgent and warning. Given this view, it would be great if we could create styles for each, and then another set of styles which is applied only when the two values appear together.

Although we can accomplish this with relatively ordinary CSS1-style selectors (we'll see how in a moment), we can also do it a little more precisely with attribute selectors. First, let's consider what we want for our styles. Warning text should be red, we decide, and urgent text should be boldfaced. If something is both a warning and urgent, then the font size should be 120% the normal font size. In addition, we want this to be true for all elements, not just paragraphs. Okay, here's what we do:

*[class~="urgent"] {color: red;}
*[class~="warning"] {font-weight: bold;}
*[class="urgent warning"] {font-size: 120%;}

Notice the difference? The first two selectors use a tilde-equal sign combination ( ~= ), whereas the third just has a plain equal sign.

When the equal sign in an attribute selector is preceded by a tilde ( ~ ), that means that the selector will match if the value listed is any one of the space-separated values of the given attribute. So the first rule's selector, *[class~="urgent"] , will match any of the following elements:

<p class="very urgent really">
<table class="urgent">
<ul class="not urgent">
<pre class="not terribly urgent but still worth knowing">

So long as the value urgent appears in the list of values, then the element will match and be colored red. This is true even if urgent is the only value in the list, as we see with the TABLE in the previous example. It's also perfectly happy to match not urgent, so remember to be careful with your class values in order to avoid semantic strangeness.

On the other hand, assume we took out the tilde, so we were left with *[class="urgent"]. Given this selector, only the TABLE would match, because it's the only element whose value exactly matches the value shown in the selector.

Attribute Selectors and Traditional Classes

Now, this may make it seem as though *[class="urgent"] and *.urgent are the same, but in fact they are not. Instead, according to CSS2, *.urgent is equivalent to *[class~="urgent"]. That's right, a traditional class selector will match any one of the values in a list of values. According to the specification, that is; in the real world, many older browsers don't act this way. Of course, those browsers don't seem to support multiple values for a given attribute, so that might explain why they have trouble here.

If you want to use traditional-style class selectors, but want to more precisely match multiple values, you can string them together, like this:

*.urgent.warning {font-size: 120%;}

Remember, though, that this is not an exact match. The preceding rule would match all of the following:

<p class="urgent warning">
<ul class="not an urgent warning">
<pre class="this warning is not at all urgent">

The last element there illustrates another aspect of this kind of selecting: it is not order-sensitive. All that has to happen for a match to occur is that the values in the selector have to appear in an element's attribute in any order. So you get matches for p.red.white.blue from the following:

<p class="red white blue">
<p class="blue red white">
<p class="hail the red white and blue">
<p class="my white and red cat is feeling blue">

The only way to select only <p class="red white blue"> is to use a non-tilde attribute selector, like this:

P[class="red white blue"]

This would not match <p class="blue red white"> because the values are in a different order. If you want to match any element with only those three values, but with the values in any order, and you have to use attribute selectors, then you would need to write:

P[class~="red"][class~="white"][class~="blue"]

That's a lot more typing than p.red.white.blue, obviously. For this particular selection, it really only makes sense to go with attribute selectors if you're writing stylesheets for non-HTML documents, which probably don't have inherent notions of class. For example:

article[author~="Eric"][author~="Meyer"]

This would select author values of Eric Meyer, Eric Meyer, Meyer Eric, and written by Eric Meyer. It would not, however, select either EricMeyer, Eric_Meyer, or even Meyer, Eric-that comma fouls things up.

Of course, similar possibilities exist with ID attributes and values. More interesting, though, is the ability to select from one of a number of values in attributes other than class and id.

Reaching Other Attributes

Consider a case where you have, in a document, a number of images. Each of these has alt text, as it should, and each one's text says something like "Figure 5". So every image which is also a figure has the word "Figure" in its alt text.

In other words, the word "Figure" is one of a space-separated list of values. So you can select all of the figures like this:

IMG[alt~="Figure"]

Now you can give all your figures a consistent margin, or a border, or float them all to the right, or whatever else you want to do. Assuming, of course, that they all have the appropriate alt text. You don't even have to class the images in order for this to work, which can really cut down on the amount of markup you have to write.

Actually, given common HTML, the uses for this particular feature are largely limited to the class, id, and alt attributes. In an XML-based markup language, though, the possibilities are nearly infinite, and it's in such circumstances that attribute selectors really come in handy.

Still More To Come

So far we've managed to cover attribute selectors in ways which let us make precise selections, and select from one value among many as well. In the next (and final!) installment, we'll look at another way to select a whole range of similar values, as well as ways to combine different attribute selectors to get really specific. Until then, don't forget about the CSS Selectors Chart, which breaks down support for all of the subjects covered in this CSS2 selector series.


Eric is editor of Web Review's Style Sheets Reference Guide, and author of Cascading Style Sheets: The Definitive Guide from O'Reilly and Associates.


Previously in Sense of Style

Attribute Selectors
New Pseudo-Classes
The Adjacent-Sibling Selector


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.