Hour 8. Advanced Selectors

wax ka badal
What You'll Learn in This Hour
  • How to create CSS rules that select only those tags that have a specific attribute
  • How to create rules based on the values of those attributes
  • How to create rules that select direct children of another element and why you'd want to do that
  • How to select an element that directly follows another element

|}

./ ADD NAME=CH08LEV1SEC1.HTML

Attribute Selectors

wax ka badal

An attribute selector tests for the existence, and possibly the values, of any specific HTML attributes set on an element. You'd use an attribute selector if you wanted all elements with a certain attribute to be styled a certain way. For example, noshade is an HTML attribute for the


tag; it means that there shouldn't be any shading effects applied to the tag. If you wanted all those


tags to be colored silver, you'd use an attribute selector based on the noshade attribute. The simplest form of attribute selector is simply the attribute within square brackets, as follows:

element[attribute] { declaration; }

For example:

hr[noshade] { color: silver; }

This rule would declare that all


elements with the noshade attribute should be colored silver.

You can write an attribute selector rule so that it selects all elements with the chosen attribute by using the universal selector (*). For example, you could set a specific rule for all tags that have a title attribute to indicate which parts of the page will pop up a tooltip when you move the mouse over them, as in the following:

*[title] { background-color: yellow; }

This marks with a yellow background all tags with title attributes. Because the universal selector is optional, you can also write the rule like this:

[title] { background-color: yellow; }
Watch Out!

Internet Explorer (up to version 5.5) does not support attribute selectors. For compatibility with older Internet Explorer versions, you can use an explicit class attribute and class selector rule. For example, to make the two attribute selector examples work in Internet Explorer 5.5, you'll need to write your HTML like this:

<hr class="unshaded" noshade>
<a href="summer2001.html" class="hastooltip"
 title="What I Did for Summer Vacation">Summer 2001</a>

Your CSS rules would then look like this:

hr[noshade], hr.unshaded { color: silver; }
*[title], .hastooltip { background-color: yellow; }
 Selecting by Attribute Value 

In addition to checking for the existence of the attribute, you can also select by attribute value. There are three ways to do this:

element[attribute="value"] { declaration; }
element[attribute~="value"] { declaration; }
element[attribute|="value"] { declaration; }

The first version designates an exact match; it selects only those elements for which the attribute has the given value. The second registers a match if the value in the rule is one of several values given in the HTML, separated by spaces. The third matches the rule's value against the HTML's value and compares the characters before hyphens. (This is to allow matching of language groups, which are written as en-us, en-uk, en-au, and so on. See [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch05.html#ch05 Hour 5], "Selectors," for a listing of some common language codes.) [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08table01 Table 8.1] shows several types of selectors and attribute values and indicates whether or not each selector would match the HTML.

CSS Selector HTML Snippet Match?
table[summary="layout"]
Yes
table[summary~="layout"]
Yes
="layout"]
Yes
div[class="bar"]
No
div[class~="bar"]
Yes
="bar"]
No
*[lang="en"] Yes
*[lang~="en"] Yes
="en"] Yes
*[lang="en"] No
*[lang~="en"] No
="en"] Yes
*[lang="en"] No
*[lang~="en"] No
="en"] No

Let's look at an example of attribute selectors in action. [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08ex01 Listing 8.1] is an HTML page consisting of a table of departure times for airline flights. I've chosen to use the axis attribute on table cells to group similar types of flights. axis is an HTML 4.01 attribute that allows for groupings of related table cells. Those flights that fly through Saint Louis have been assigned an axis value of stlouis, whereas those going through Chicago are labeled with an axis value of ord.

Listing 8.1. HTML Table Marked Up with the axis Attribute
<!-- flights-8.1.html --><br /><html><br /><head><br /><title>Flights from Los Angeles to New York</title><br /><link type="text/css" rel="stylesheet"<br />href="flights-8.2.css"><br /></head><br /><body><br /><h1>Schedule of Flights</h1><br /><h2>Los Angeles to New York</h2><br /><table><br /><tr> <th>Monday</th> <th>Tuesday</th> <th>Wednesday</th><br /><th>Thursday</th> <th>Friday</th> </tr><br /><tr> <td axis="ord">09:13 (ORD)</td><br /><td axis="ord">09:13 (ORD)</td><br /><td>10:17 (direct)</td><br /><td axis="ord">09:13 (ORD)</td><br /><td>10:17 (direct)</td> </tr><br /><tr> <td axis="stlouis">12:05 (STL)</td><br /><td axis="stlouis">12:05 (STL)</td><br /><td axis="stlouis">12:05 (STL)</td><br /><td axis="stlouis">12:05 (STL)</td><br /><td axis="stlouis">12:05 (STL)</td> </tr><br /><tr> <td axis="ord">17:15 (ORD)</td><br /><td axis="stlouis">13:44 (STL)</td><br /><td axis="ord">17:15 (ORD)</td><br /><td axis="stlouis">13:44 (STL)</td><br /><td>14:30 (direct)</td> </tr><br /><tr> <td></td><br /><td axis="ord">17:15 (ORD)</td><br /><td>19:20 (direct)</td><br /><td axis="ord">17:15 (ORD)</td><br /><td axis="ord">17:15 (ORD)</td> </tr><br /></table><br /></body><br /></html><br />

The cascading style sheet for this example is shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08ex02 Listing 8.2]; you'll use attribute selectors to set up rules on each flight type to show them with different background colors. This effect is shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08fig01 Figure 8.1].

Figure 8.1. Using attribute selectors to make axis values visual.
[file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/images/08fig01_alt.jpg [View full size image]]
File:08fig01.jpg
Listing 8.2. This Style Sheet Uses Rules Based on the axis Attribute Selector
/* flights-8.2.css */<br /><br />body { font-family: Verdana, sans-serif; }<br /><br />td { border: 1px solid black;<br />padding: 0.25em;<br />color: black;<br />background-color: white; }<br /><br />td[axis="stlouis"]<br />{ background-color: silver;<br />color: black; }<br /><br />td[axis="ord"]<br />{ background-color: black;<br />color: white; }<br />

You've been using shorthand versions of some attribute selectors for some time now; the class and id selectors are just special cases of an attribute value selector. The following pairs of rules are equivalent:

.apple { color: green; }
*[class~="apple"] { color: green; }
#banana { color: yellow; }
*[id="banana"] { color: yellow; }

You can combine multiple attribute values together by simply adding on another attribute test. Here's an example of a rule that selects all table cells that are right-aligned and vertically aligned to the bottom:

td[align="right"][valign="bottom"]
 { font-size: small; }
Did you Know?

You can use attribute selector rules with a user style sheet to create some very simple but powerful testing tools for web development. For example, to make anchors visible, create a style sheet, set it as your user style sheet in your browser, and add the following rule:

a[name], [[Image:135fig01.jpg|8px]] { border: 1px dotted red; }

This puts a dotted line around your anchors and anything else with the id attribute set. You can use this same trick to make table borders, form boundaries, field <label>s, and other block elements visible because they're outlined with a border. Here's a pair of rules to make it very clear which of your images don't have alt attributes on them:

img { border: 5px solid lime; }
img[alt] { border: none; }
 Family Relationships 

Family-based selectors in CSS choose elements based on the relationships between the HTML tags; these relationships are named after family relationships. You've already used one of the family relationship selectors: the descendant selector, which selects elements descended from another tag. Other relationship selectors include child and adjacent sibling selectors.

 Child Selectors 

A child selector is a special case of descendant selectors, which were covered in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch05.html#ch05 Hour 5]. A child selector identifies only those elements that are immediate children of another element, not any "grandchildren" or other descendants. A child selector is indicated by a greater-than symbol (>) between the parent element and the child:

parent > child { declaration; }

For example, consider the following snippet of HTML:

<blockquote>
 <div class="opinion">
 <p>I'm voting Green next year.</p>
 <p>I'm wearing green, too!</p>
 </div>
</blockquote>

Here are some style rules, but only a few of these will be applied to the code sample:

blockquote p { font-size: large; }
blockquote > p { font-family: Arial, sans-serif; }
.opinion > p { font-color: green; }
The first rule is used on the quote; it's a normal descendant selector, and both of the paragraphs are within a

. The second rule is not applied; there are no

tags that are direct children of a

tag; both of them are direct children of the

. (They're descendants of the

, of course, but only direct children, not grandchildren, count for child selectors.) The third rule is applied to the

text because both paragraphs are direct children of a tag with class="opinion". So the total effect will be two green paragraphs, both in the default font face.

Watch Out!

Some older browsers, notably Internet Explorer 6 and earlier, don't recognize child selectors. For compatibility with these older browsers, use descendant selectors; if you're unable to get the effects you want with just descendants, use class selectors too. Here's how you would rewrite the green quote style sheet rules:

blockquote p { font-size: large; /* same */ }
blockquote p.childofblockquote
 { font-family: Arial, sans-serif; }
.opinion p { font-color: green; }
You'll notice the additional class called childofblockquote; it has to be added to every

that is a direct child of a

.

Did you Know? Internet Explorer's lack of support for child selectors has a silver lining. Because rules with child selectors are ignored, you're able to write styles that are understood by most other modern browsers but aren't displayed by Internet Explorer. This is an example of a browser filter; you'll learn more about those in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch24.html#ch24 Hour 24], "Troubleshooting and Browser Hacks."

Adjacent Sibling Selectors

Two HTML tags are siblings if they have the same parent; they are adjacent siblings if the second occurs directly after the first in the source code. Here's some HTML to illustrate a sibling relationship:

<ul>
 <li id="greg">Greg</li>
 <li id="peter">Peter</li>
 <li id="bobby">Bobby</li>
 <!-- id attributes are included for reference -->
</ul>

The

  • elements are all siblings of each other. The greg and peter
  • tags are adjacent siblings, and the peter and bobby
  • tags are adjacent as well. However, the greg and bobby tags are not adjacent. An adjacent sibling selector makes a selection based on two adjacent siblings, but it applies the declared style only to the second of the two. This is very important to remember: You are not selecting the pair; you are selecting only the final one in the list. You write an adjacent sibling rule by listing the first sibling, a plus sign (+), and then the second sibling. A rule such as the following turns only the Peter and Bobby names blue, because they're li elements that directly follow another li element:
    li + li { color: blue; }
    
    Watch Out! Like many other advanced selectors in CSS, the usefulness of adjacent sibling selectors has been crippled by a lack of browser support in Internet Explorer. Using the same techniques described previously in this hour, you can add a number of class attributes and selectors and approximate the behavior for those older browsers that don't support CSS Level 2 selectors. This isn't the best solution, but it's the only one that works now.

    Adjacent sibling selectors are useful for adding or removing margins, padding, and borders when siblings are meant to flow together visually. An example of this is shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08ex03 Listing 8.3].

    Listing 8.3. A Definition List with Adjacent
    and
    Elements
    <!-- acronyms-8.3.html --><br /><html><br /><head><br /><title> Some Common Acronyms </title><br /><style type="text/css"><br />body { font-family: Verdana, sans-serif; }<br /><br />dt { font-weight: bold; }<br /><br />dt + dt, dd + dt<br />{ margin-top: 1em;<br />font-weight: bold;<br />padding-top: 1em;<br />border-top: 1px solid black; }<br />/* These rules apply to any dt that follows<br />another dt, or a dd. The only dt that<br />would not match such a rule is the first<br />one, which is a direct child of the dl. */<br /><br />dt + dd { margin-top: 0.5em; }<br />/* This applies to any dd that immediately follows<br />a dt. It doesn't apply to a dd that follows<br />another dd. */<br /><br />dd + dd { font-size: small;<br />border: 1px;<br />padding: 0.1em; }<br /><br />/* This rule selects any dd that follows another<br />dd, but not to a dd that follows a dt. */<br /><br /></style><br /></head><br /><body><br /><h1>Common Acronyms</h1><br /><br /><dl><br /><dt>CSS</dt><br /><dd>Cascading Style Sheets</dd><br /><br /><dt>HTML</dt><br /><dd>Hypertext Markup Language</dd><br /><dd>See also: <cite>XHTML</cite></dd><br /><br /><dt>WAI</dt><br /><dd>Web Accessibility Initiative</dd><br /><dd>See also: <cite>W3C</cite></dd><br /><br /><dt>WCAG</dt><br /><dd>Web Content Accessibility Guidelines</dd><br /><br /><dt>WWW</dt><br /><dd>World Wide Web</dd><br /><br /><dt>WWWC -- see <cite>W3C</cite></dt><br /><br /><dt>W3C</dt><br /><dd>World Wide Wide Consortium</dd><br /><dd>See also: <cite>WAI</cite></dd><br /><br /><dt>XHTML</dt><br /><dd>Extensible HTML</dd><br /><dd>See also: <cite>HTML</cite></dd><br /></dl><br /></body><br /></html><br />

    The embedded style sheet in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08ex03 Listing 8.3] uses styles based on adjacent-sibling rules applied to a definition list. In HTML, a definition list is declared by the
    element, which can only have
    (term) or
    (definition) elements as children; this is important for understanding why the adjacent-sibling rules work as shown in [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08fig02 Figure 8.2].
    Figure 8.2. Adjacent sibling rules improve the look of a definition list.
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/images/08fig02_alt.jpg [View full size image]]
    File:08fig02.jpg

    ./ ADD NAME=CH08LEV1SEC2.HTML

    Although unsupported by all but the newest browsers, advanced selectors add considerably to the CSS developer's toolbox. Attribute selectors allow styles to be set based on specific attribute values or even the existence of an attribute on the tag. Relationships between elements can be expressed in CSS by the child selector, which applies to direct children of a specific element, and by the adjacent sibling selector, which chooses the second of a pair of specified tags.

    ./ ADD NAME=CH08LEV1SEC3.HTML

    The workshop contains a Q&A section, quiz questions, and activities to help reinforce what you've learned in this hour. If you get stuck, the answers to the quiz can be found after the questions.

    Q&A

    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa1q1a1 Q.] Can I do pattern matching in attribute values? Suppose I want to select all <a> tags that are mailto links. Can I use a[href="mailto:*"] as my selector?
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa1q1 A.] Nope. The CSS specifications don't define a way to do this type of pattern matching. Future versions of CSS based on XPath and XPointer might allow this, but for now there is no way to use pattern matching in CSS. To make your mailto links stand out, set a class attribute on them and use a class selector.
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa1q2a2 Q.] If I could use either a child selector or a descendant selector, which should I use? For example, if I want to select all <img> tags within <a> links.
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa1q2 A.] In theory, it's better to use a child selector if you know you're dealing with a direct child because it's quicker for the browser to calculate child selectors. It doesn't have to look over the full tree of the HTML document, just up one level. In practice, though, you are better off sticking with the descendant selector because of poor browser support; don't rely on a child selector alone. You can use both, if you like.
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa1q3a3 Q.] Can I combine advanced selectors with simple selectors or other advanced selectors?
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa1q3 A.] Certainly! This is a valid CSS rule:
    .chap > th + td img[alt] { border: 2px solid green; }<br />

    What would match this? Basically, anything that meets the following criteria:

    • An image element
    • With an alt attribute set (to any value)
    • Where that image is a descendant of a table cell
    • Assuming that table cell has a table header cell as a sibling
    • Which is a direct child of an element in the chap class

    Quiz

    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa2q1a1 1.] What does the + symbol indicate, in a selector?
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa2q2a2 2.] Which selector will select the HTML element

    Welcome

    , and why?
    #
    h1[align~="right"]
    1. *[align="right"]
    2. [align|="right"]
    3. H1[align]
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa2q3a3 3.] You're using Opera 8.5 and you want to write a rule in your user style sheet to hide banners that are 468 pixels across and 60 pixels high. How do you write that rule?

    Answers

    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa2q1 1.] The + symbol designates a direct sibling selector.
    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa2q2 2.] It's kind of a trick question. All of them will select the

    . The first will select it because right is one of the values listed in the attribute (it's the only value, too). The second will select it because it's exactly the value (and the selector's type is universal). The third is also a universal selector, and it will compare values before a dash; because there is no dash, it will compare just right with right. The last matches because the

    tag has an align attribute, with any value.

    [file:///C:/Documents%20and%20Settings/dani/Asztal/Sams%20Teach%20Yourself%20CSS%20in%2024%20Hours_2ndEd/0672329069/ch.htm#ch08qa2q3 3.] Here's one way to zap away those annoying banners:
    img[height="60"][width="468"] { display: none; }<br />

    Exercise

    You'll master selectors gradually, as you work on other projects using CSS and write style sheets using these types of rules. To practice as you learn, make a "cheat sheet" to remind yourself which advanced selectors you can use, and keep that list handy as you read this book and create style sheets. Identify specific situations in which a complex rule might actually work better than simply adding class and id in HTML, which is an easy habit to fall into.

    ./ ADD NAME=CH09.HTML