Attribute Selectors

Web Review
August 2000

In our ongoing series of articles on CSS2 selectors, we've covered a number of topics, from the universal selector to the adjacent-sibling selector, and most recently, a variety of pseudo-elements. As fascinating as these have been, in many ways they've just been a warmup for the topic of the final articles in the series: attribute selectors. Starting with this piece, I'll cap off the selector series with a three-article look at attribute selectors, and the surprising ways they can help you style your Web pages.

Simple Attribute Selection

The syntax for attribute selectors is simple enough, but it doesn't look like anything found in CSS1. An attribute selector involves the use of an element selector, or the universal selector, followed by an attribute enclosed in square brackets. For example, let's say we want to select all anchors with an href attribute. The value of the href doesn't matterÑwe're just selecting anchor elements which have that attribute present. So we write:

A[href] {color: green;}

This rule will set any hyperlink to be green. The advantage is that the shown rule will select all hyperlinks, visited or otherwise. In other words, the following two selectors are equivalent:

A[href]
A:link, A:visited

This is but one way to use a simple attribute selector. There are more practical purposes. Let's say that we want to set a border color for all images which are part of a hyperlink, and which have a border of some kind. We decide that a good color would be blue (it's tradition, after all). So in order to set this color for those images which have a border, we declare:

A[href] IMG[border] {border-color: blue;}

How about some other uses? You could employ attribute selectors in a diagnostic fashion. For example, you could set an obvious style for any element which has a class attribute of any value:

*[class] {color: red; background: yellow; border: 1px solid orange;}

With that rule, any element with a class set will be highlighted in a most eye-catching fashion. A similar strategy could be employed to pick out the table cells and headers which have been set to nowrap:

TD[nowrap], TH[nowrap] {background: red;}

It probably isn't something you'll need to include in a deployed design, of course, but it can help track down legacy markup.

As useful as this can be, it seems a bit limiting, doesn't it? After all, what good is it to apply styles to every element with a certain class, regardless of the value assigned to that attribute? What we need is a way to target specific combinations of element attributes and their values.

Selecting on Attribute Values

So you want to write selectors which use values. You do, don't you? Well, if not, you probably will by the time the section is finished.

It's possible to create selectors which target not only attributes, but also the values of those attributes. The general syntax is:

element[attribute="value"]

The value in the selector must exactly match the value found in the document, just as the element and attributes must also match exactly. Therefore, if you put a value of 2px in the selector, and the document consistently uses 2, the selector won't match.

Let's say that you want to write styles such that all the links on your pages which point to your home page are boldfaced. The CSS1 way to do this would be to add a class attribute to each link which points to your home page, and give that class a value something like "homelink." Then you would write:

A.homelink {font-weight: bold;}

That's how it works in CSS1. It's kind of cumbersome, given that you have to specially class the relevant links. In CSS2, attribute selectors remove the need for special-case classing of this sort by letting you write the following:

A[href="http://my.home.page/"] {font-weight: bold;}

Assuming the URL of your home page is http://my.home.page/, this rule will boldface any hyperlink on the site which points to your home page. Remember, though, that this will only work if the value found in the document is exactly the same as what's in the selector. In order to cover possible variations, you might want to try this:

A[href="http://my.home.page/"], A[href="http://my.home.page"] {font-weight: bold;}

So that's how you select for a particular value of a given attribute of a given element. Here's another example:

IMG[alt=""] {visibility: hidden;}

There, we've set any image with an empty alt attribute to be hidden. Why? To get an idea of what parts of the page will be "invisible" to text-based and speaking browsers. Again, it makes a good diagnostic tool, although it isn't necessarily something you'll want to do in everyday design.

Something Old Made New

It's also possible to replace class and ID selectors with attribute selectors. Whether or not you would choose to make this replacement is another question. Consider the following selectors:

P[class="warning"] {color: red; background: white;}
H1[id="page-title"] {font-size: 250%; border-bottom: 1px solid gray;}

So any P element with a class of warning will be red on white, and any H1 element with an id of page-title will be larger and get a bottom border. Of course, we could use these styles to almost the same effect:

P.warning {color: red; background: white;}
H1#page-title {font-size: 250%; border-bottom: 1px solid gray;}

Note that I say "almost the same effect," which is another way of saying that it isn't exactly the same. Why not? We'll explore this in detail in the next article, but for now I'll mention that P.warning would match the following:

<p class="warning note">

Whereas the attribute selector P[class="warning"] would not. Again, we'll be exploring this in detail in the next article, so stay tuned.

So, besides a desire to inflame our carpal tunnel syndrome and achieve a little more precision, what reasons would there be to go with the attribute selectors when we're trying to select for class values? When it comes to HTML, there aren't many. However, that's because the .class and #id behaviors are already defined for HTML. Other languages, such as those based on XML, may not honor such conventions, in which case you'll need to use attribute selectors. One example:

article[author="Eric Meyer"] {font-weight: bold;}

This will cause any element article with an attribute of author that's been given the value Eric Meyer to be boldfaced. Once more, remember that the value must match exactly, so this rule will not match values of Eric Meyer, E. Meyer, or even EricMeyer.

Support

At this writing, only Opera 4 and some Mozilla builds support attribute selectors. Fortunately, the browsers which don't support attribute selectors seem to ignore them completely.

A Good Beginning

The ability to select for attributes and values is a powerful one, but the techniques we've covered in this article are just a beginning. Still to come are ways to select from one of a number of values, methods for picking values which begin with the value you specify, and more. You might also be interested in a pair of articles I published on the O'Reilly Network. These describe ways to employ user stylesheets for both good and evil, and many of the methods described depend on attribute selectors.