Attribute Selectors, Part 3

Web Review
August 2000

We've come a long way with this seriesÑfrom the universal selector all the way to the attribute selectors, which we've been exploring in the previous two articles. In this, the final (for now) article in this series, we'll look at another kind of attribute selector, talk about ways to use multiple attributes in one selector, and then wrap up everything into a nice summary.

Matching Hyphenated Values

Although we don't think of it often, the Web really is a multilingual arena. Just because we're used to seeing everything in English, it doesn't have to be that way. HTML, for example, allows elements to be marked in terms of what language they employ. English, for example, would be marked with en as a value of the attribute lang. Thus:

<p lang="en">This is in English.</p>

As I say, though, English isn't the only possibility. There's German (de), French (fr), Japanese (jp), and hundreds more.

Within each of these languages are many more dialects, such as American English, UK English, Canadian English, or even Cockney English. These are generally represented with the base language code, like en, followed by a hyphen (-), and then the dialect in question. So we could have:

<p lang="en">This is in English.</p>
<p lang="en-US">This is in, like, American English, y'know?</p>
<p lang="en-UK">I say, this seems to be in UK English.</p>
<p lang="en-Can">This is in Canadian English, eh?</p>

Okay, so let's say we want to write a selector which will match any element which is marked as being in English. With the attribute selectors we've seen so far, we'd have to write something like this:

*[lang="en"], *[lang="en-US"], *[lang="en-UK"], *[lang="en-Can"]

And that's only to select those four types of English. What about others? How long will this selector grouping have to become?

Here's where the vertical bar comes to our rescue. Behold!

*[lang|="en"]

This selector will match any element with an attribute of lang whose value begins with en, and is either on its own or is immediately followed by a hyphen and some extra information. No spaces, by the way: en -UK is not the same as en-UK. So the selector not only matches all of the hyphenated rules, but en as well.

Taking Hyphens Further

We aren't restricted to using this type of selector with lang, though. Consider a document where all of the figures have alt text of fig-1, fig-2, and so on. We can match them by writing:

IMG[alt|="fig"]

As always, this only works if your alt text is properly written. And, in this case, you would not only match alt text such as fig-3, but also the text fig-tree. The selector would not match figure or config, since neither one begins with fig- or is simply fig.

Similarly, you could select any image whose filename begins with "fig-" by writing:

IMG[src|="fig"]

However, this will only work with relative URLs, and only if they're in the same directory. In other words, src="fig-3.gif" will be matched, but src="pix/fig-3.gif" will not.

Another way to use this is if you have several related classes, all of which have the same beginning. For example:

P.example-graphic, P.example-text, P.example-list, P.example-table

could be rewritten:

P[class|="example"]

So, given the proper planning, you can do quite a bit with this attribute selector.

Combining Attribute Selectors

Not only can you do everything we've talked about thus far, but you can combine them in a single selector. Let's say you want to apply a red coloring to any HTML-based hyperlink which has a class that contains the word "external" and is marked as being in some version of German. Here's the selector:

A[href][class~="external"][lang|="de"] {color: red;}

So wherever we find an a element which has an href attribute (the actual value doesn't matter), a class attribute which contains the value external, and a lang attribute which indicates a German dialect, the element will be colored red.

That's probably a little too specific for most tasks, but it does admirably illustrate how attribute selectors can be used.

So Where Have We Been?

At this point, it's worth going over the various new selectors we've discussed. To that end, I present a modified version of the summary table found in the CSS2 specification.

Pattern Meaning Examples
* Matches any element. * {color: purple;}
X > Y Matches any element Y that is a child of an element X. P > STRONG {color: red;}
UL > LI {font-weight: bold;}
X:first-child Matches element X when X is the first child of its parent. P:first-child {font-size: 120%;}
X:hover
X:focus
Matches X during certain user actions. A:hover {color: red;}
INPUT:focus {background: purple;}
X:lang(Y) Matches element of type X if it is in (human) language Y. The document language specifies how language is determined. P:lang(fr) {background: black; color: white;}
X + Y Matches any element Y immediately preceded by an element X. H1 + P {margin-top: 0;}
EM + STRONG {color: gray;}
X[foo] Matches any element X with the foo attribute set (whatever the value). A[href] {text-decoration: underline;}
IMG[alt] {border: 2px solid gray;}
X[foo="bar"] Matches any element X whose foo attribute value is exactly equal to bar. A[href="http://www.webreview.com/"] {color: green;}
IMG[src="figure4.jpg"] {display: none;}
X[foo~="bar"] Matches any element X whose foo attribute value is a list of space-separated values, one of which is exactly equal to bar. P[class~="warning"]
IMG[alt~="Figure"]
X[foo|="bar"] Matches any element X whose foo attribute has a hyphen-separated list of values beginning (from the left) with bar. P[lang|="jp"]
IMG[alt|="fig"]

That's a Wrap

Wow! Seven articles spanning three months is a long time to spend on one subject, but I think we can agree that it was worth it. Even though not every browser out there can recognize all that we've seen, there are enough of them available for you to start experimenting, and even to use these selectors on public pages (carefully!). When in doubt, refer to the CSS2 Selectors Chart for more information on what's supported by whom.

Thanks for coming along with me on this ride, and I hope you'll be back for my next article on CSSÑwhatever the subject turns out to be!