Chapter 7. New CSS language features – Hello! HTML5 & CSS3: A user-friendly reference guide

Chapter 7. New CSS language features

 

This chapter covers

  • Selecting elements based on their parents
  • Selecting elements based on their siblings
  • Selecting elements dynamically according to user activity

 

Let’s remind ourselves what a CSS rule looks like.

In this chapter we’re concerned entirely with the parts of CSS that appear outside of the curly brackets—the selectors and associated syntax that makes up a CSS document. After this chapter, we’ll concentrate almost completely on the stuff that appears inside the curly brackets—the properties and values that define the visual effect to be applied. The stuff that appears inside the curly brackets is naturally more interesting, because that’s what lets you change the style of your pages. But being able to choose what elements your styles affect is crucially important for the whole thing to work.

 

What is CSS3?

CSS3 is the third major revision of the W3C CSS specification. Unlike the previous two revisions, CSS3 is divided into modules—instead of being one, long document like CSS1 and CSS2/2.1, there are currently more than 30 individual documents that are part of CSS3. These are all allowed to progress and mature at their own rates; depending on the level of interest, some modules will progress to level 4 before the level-3 work is completed.

Like the term HTML5, the term CSS3 is often given a wider definition than just the specifications. Many of the features people consider to be CSS3 are actually in CSS2.1.

 

Choosing elements through their relationships

Here are screenshots of three popular websites, showing three different but common design requirements.

Alternating table rows have a different style.

Links to the current page or section have a different style.

The first and last elements have a different style.

Using traditional approaches, you would have to apply classes to each element. For the previous three examples, the code would be something like the following, where the class names don’t add any further meaning to the markup—they just make explicit relationships that are already present:

<table>                  <ul>                     <ul>
 <tr class="odd">         <li>                     <li class="first">
  <td></td>                <a href="/home"          top + right border
 </tr>                        class="current">       </li>
 <tr class="even">           Home                       <li>
  <td></td>                </a>              right border
  </tr>                    <a href="/other">       </li>
</table>                    Other                  <li class="last">
                           </a>                     bottom + right
                          </li>                   border
                         </ul>                     </li>
                                                  </ul>

In CSS3, thanks to all the new selectors available, you can take advantage of those relationships directly with no need to add extra class attributes. In this section, you’ll learn about the key ways of selecting elements with CSS combinators and pseudo-classes.

Selecting sets of elements with combinators

Combinators allow you to chain simple selectors together. They’re the workhorses of CSS. The following diagrams show a simple HTML fragment as a tree structure and then highlight the elements that the different rules select using the common CSS2 combinators.

<article>
<p></p>
<p></p>
<section>
<p></p>
<p></p>
</section>
</article>
article p {}
A space is the descendant combinator, selecting any p that is a descendant of an article element.
article > p {}
The greater-than symbol is the child combinator, selecting only the p elements that are direct children of an article.

The Adjacent-Sibling Combinator

Rather than use tree diagrams to illustrate the new selectors, we’ll use this simple document:

<header>
  <h1>Header</h1>
</header>
<article>
  <h1>Article</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
  <footer>Article footer</footer>
</article>
<footer>
  Body footer
</footer>

The complete listing is available in ch07/sibling-combinator-1.html.

This rule selects any paragraph elements that immediately follow a level-one heading element:

h1 + p { background-color: #000; }

You can see in the screenshot that only the first paragraph is selected. The + is known as the adjacent-sibling combinator. This example is from ch07/sibling-combinator-1a.html.

The target element is always listed last. This rule has no effect because there are no paragraph elements immediately after footer elements:

footer + p {
  background-color: #000;
}

Switch the two simple selectors around, and you can see that there are footers that follow paragraphs:

p + footer {
 background-color: #000;
}

See the files sibling-combinator2a.html and sibling-combinator2b.html in the ch07 folder for these two examples.

The General-Sibling Combinator

Suppose another element is inserted between the paragraph and the footer, like this:

<p>Paragraph 2</p>
<img src="example.png">
<footer>Article footer</footer>

The footer is no longer selected by p + footer because it doesn’t immediately follow the paragraph.

For this set of examples, we’ll make a slight modification to the HTML. Instead of an article footer, a blockquote element and a third paragraph have been added.

Browser support quick check: combinators   + ~
1.0 1.0
1.0 1.0
7.0 8.0
6.0 9.5
1.0 1.0
<header>
    <h1>Header</h1>
</header>
<article>
    <h1>Article</h1>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
    <blockquote>Quote</
blockquote>
    <p>Paragraph 3</p>
</article>
<footer>
    Body footer
</footer>

Elements targeted by the generalsibling combinator have to occur after the elements targeted by the preceding selector in the document. Compare the results of these two rules. There are three paragraphs after the h1, but only one of those is after the blockquote.

Listing: ch07/sibling-combinator-1b.html Listing ch07/sibling-combinator-1c.html

Selecting among a set of elements with pseudo-classes

Combinators allow you to select all elements that fit a particular relationship. But what if you don’t want to select all of the <p> elements that are descendants of an <article> element for the same styling? Or all the rows of a table? CSS pseudo-classes allow you to select the first element, the last element, or a subset of the elements according to a pattern. They remove the need to add classes to your markup for purely stylistic purposes. Before you learn about pseudo-classes, let’s consider what you would need to do if pseudo-classes didn’t exist, and why that’s not good practice, with a couple of examples.

 

The IE6 problem

IE6 is the most successful browser of all time in terms of market share, managing as much as 90% market share in its heyday. Unfortunately, it’s missing several key features of CSS2.1.

The ubiquity of IE6 allowed many organizations to get away with shortcuts in web app development. The result is that they have since been stuck with expensive-to-replace applications that only work on IE6. It’s impossible to upgrade the web browser without first replacing all those applications—a slow process. The end result is that several CSS2.1 features couldn’t be used on most websites until recently, one of which is pseudo-classes.

In the old days (you know, around 2005) when IE6 was predominant, the only way to do this consistently was to add classes all over your HTML that anticipated the styling you wanted. With CSS2.1 and CSS3 approaching 90% browser support, you should now be doing this with pseudo-classes.

 

Selecting the First and Last Element

Styling the first element of any set differently is common on the web today. This blog renders the first paragraph in a larger font to make it stand out.

The old way to approach this was to explicitly add a class to the first paragraph:

<h1>Heading</h1>
<p class="first">
  First paragraph...
</p>

This blog goes even further—the first post is styled differently than the other posts previewed on the home page. The first post takes up the full width and is divided into columns; the rest of the posts are in a single column further down. Again, the usual approach to this is to add a class in the markup:

<div class="post first">
  <h1>Post 1</h1>
  <p>...
</div>
<div class="post">
  <h1>Post 2...

For details on CSS columns, check out chapter 11.

For the next few examples, we’ll use a markup fragment in a style that’s commonly used for site navigation—an unordered list of links. The screenshot shows some default styling, putting a dotted outline around each major element so you can see where it is.

<nav>
  <ul>
     <li>
       <a href="#item1">Item 1</a>
     </li>
     <li>
       <a href="#item2">Item 2</a>
     </li>
     <li>
       <a href="#item3">Item 3</a>
     </li>
     <li>
       <a href="#item4">Item 4</a>
     </li>
     <li>
       <a href="#item5">Item 5</a>
     </li>
     <li>
       <a href="#item6">Item 6</a>
     </li>
  </ul>
</nav>

To select the first element in the list without adding additional markup, you can use the :first-child pseudo-class:

ul li:first-child {
  background-color: #000;
}

This selector is saying, “Select the <li> elements that are the first child of their respective <ul> elements.”

Selecting the last element is also straightforward with the :last-child pseudo-class:

ul li:last-child {
  background-color: #000;
}

This selector is saying, “Select the <li> elements that are the last child of their <ul> parent elements.”

Pseudo-classes can be used with descendent or child combinators like any other simple selector. Compare this with the previous example:

li:last-child {
  background-color: #000;
}
li:last-child a {
  background-color: #fff;
}

The extra rule selects all <a> elements that descend from an <li> element that is a last child. This rule has been used to make the link visible.

Selecting an Element by its Ordering

What if you don’t want to select just the first or last child? With :nth-child you can easily select specific elements by specifying a numeric parameter:

li:nth-child(3), li:nth-child(5) {
  background-color: #000;
}

The :first-child pseudo-class is just a more intuitive way of saying :nth-child(1).

These examples were taken from the 2010 Commonwealth Games website (left) and the admin pages of my own blog (right). The markup for the two is remarkably similar—each gives a specific class to each <tr> element in the table.

<table>
  <tr class="odd">...
  <tr class="even">...
  <tr class="odd">...
  <tr class="even">...
  <tr class="odd">...
  <tr class="even">...

You could use :nth-child(1), :nth-child(2), :nth-child(3), and so on to apply a style to each row in the table in order, but that would be as much work as adding a class to each row. Instead of specifying a number as the parameter to :nth-child, you can specify a pattern. Let’s look at that next.

To select every second element, use the pattern 2n:

li:nth-child(2n) {
  background-color: #000;
}

If you imagine that all the elements are numbered in order, this selects all the <li> elements with a number that matches the pattern 2n for whole number values of n.

Selecting the odd-numbered children this way looks a little more complex but follows the same pattern:

li:nth-child(2n-1) {
  background-color: #000;
}

The odd-and-even requirements are so common that there’s a shortcut keyword for each. This creates a red-and-blue striped list:

li:nth-child(odd) {
  background-color: #f00;
}
li:nth-child(even) {
  background-color: #006;
}

Selecting from the End Backward

You don’t have to select from the top down. You can select from the bottom up with :nth-last-child. It works in the same way as :nth-child:

li:nth-last-child(2n) {
  background-color: #000;
}

The hypothetical values for n extend to negative numbers, as can be seen if you try this:

li:nth-last-child(2n+2) {
  background-color: #000;
}

You’ll notice that 2n+2 has results identical to 2n and to 2n-2.

But if n is negative, different rules apply. Now n will count backwards from the elements you see; if there are six elements it will count six back. So adding a fixed number to it will move the range of selected elements so that it selects that number of visible elements. This selector will target just the first three elements:

li:nth-child(-n+3) {
  background-color: #000;
}

The same trick works with :nth-last-child except, as with last child, the counting is from the end of the set of elements up. This selects just the last two odd-numbered items:

li:nth-last-child(-2n+4) {
  background-color: #000;
}

More Complex Selection Patterns

If you increase the number in front of n, then the pattern extends over more elements. This rule selects the middle element out of each set of three:

li:nth-last-child(3n-1) {
  background-color: #000;
}

Of course, this still targets only one element out of every three. You’d need an extra rule if you wanted a pattern ABC instead of ABA.

Now the answer to the mini-quiz AJ posed earlier. Here’s the code again. The result is shown in the screenshot:

ul :last-child {
  background-color: #000;
}

Did you guess right? Without specifying that only <li> elements that were last children should be styled, the rule now selects any element that is a last child. The <a> elements are all the last child of their respective parent <li> elements.

You may be thinking to yourself that there are a few situations in which you would like to select elements that are both first and last child, like the links in this example. You can do this by combining the two pseudo-classes:

ul :first-child:last-child {
  background-color: #000;
}

This rule selects elements that are both a first and a last child and are descendants of the <ul> element. It’s a bit of a mouthful, though, so fortunately there’s an alternative pseudo-class that has the same effect:

ul :only-child {
  background-color: #000;
}
Browser support quick check: child selectors   :first-child :last-child :nth/:nth-last child/of type
1.0 1.0 1.0
1.0 1.0 3.5
7.0 9.0 9.0
7.0 9.5 10.10
1.0 1.0 3.0
Selecting by Type of Element

Sometimes, if the structure is likely to vary, the element you want to select isn’t consistently the first or last (or second or third) child. Here each article has a picture, but it’s located in a different place in each one:

<header>
  <h1>Header</h1>
</header>
<article>
  <h1>Article 1</h1>
  <img src="example.png">
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</article>
<article>
  <h1>Article 2</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
  <img src="example.png">
</article>
<footer>
  Body footer
</footer>

How would you write a selector for the last paragraph of each article? Or could you select the first article? Let’s try using :first-child and :last-child:

article:first-child {
  background-color: #000;
}
p:last-child {
  background-color: #000;
}

As the screenshot shows, these rules have no effect. The naive solution fails because neither <article> nor <p> is the first child of any container.

The first article is the second element on the page. You could select it with article:nth-child(2), but that would be a fairly fragile solution—it would break if someone decided to add an advertising banner between the header and the first article. Each article starts with an <h1>, but then one article leads with a picture, and the other leads with a paragraph. In this case, p:nth-child(2) would only select the last paragraph in the first article.

It’s for situations exactly like these that we have the :first-of-type pseudo-class:

article:first-of-type {
  background-color: #000;
}

This selector will always apply to the first article element on the page, as well as any other first article elements further down the tree. Note that the image isn’t transparent so you can’t see the background behind it.

The last-of-type pseudo-class works in the same way, except in reverse:

p:last-of-type {
  background-color: #000;
}

If you don’t want the last or the first, or you want to style according to a pattern, you can use :nth-first-of-type and :nth-last-of-type. This work in the same way as :nth-child except that the only elements that take part in the count are those specified by the simple selector to which you apply the pseudo-class.

Choosing elements by their attributes

You should by now be aware that CSS provides convenient shorthand for selecting elements according to their class and ID. But class and ID are just two of many attributes that can be applied to HTML elements. Here are some common scenarios with another common attribute, the href on links.

Different styling for external links Different styling for an element based on the URL Different styling for file downloads

If you were using HTML4 and IE6-compatible CSS2, you’d probably implement these examples by adding an explicit class to the elements concerned:

<a                          <a                    <a
 class="external"            class="home"          class="pdf"
 href="http://site.com/      href="/home">         href="doc.pdf">
">                            Home                  Download document
  Visit site                </a>                  </a>
</a>

In these examples, the class attribute is really just duplicating information available in the href attribute. Whenever there’s duplicate information, there’s an opportunity for the two sets of information to get out of sync. For example, what if the document in the third example changes from a PDF to a Word document, so someone updates the link but forgets to update the class? The link would be styled as a PDF, but it would actually be a Word document. Wouldn’t it be handy if there was some way you could select elements based on those other attributes rather than relying on classes and IDs?

CSS3 makes it possible to write selectors that target these elements based on the values in the href attribute; these are called attribute selectors. One excellent opportunity to use attribute selectors is microdata. Remember the sample hCard from chapter 2? Here’s the listing again.

Browser support quick check: attribute selectors   [] = ^ $ * ~
1.0 1.0
1.0 2.0
7.0 7.0
7.0 9.0
1.0 1.0

<section id="rob" itemscope
 itemtype="http://microformats.org/profile/hcard">
  <h1 itemprop="fn">Rob Crowther</h1>
  <p itemprop="n" itemscope>Full name:
    <span itemprop="given-name">Robert</span>
    <span itemprop="additional-name">John</span>
    <span itemprop="family-name">Crowther</span>
  </p>
  <p itemprop="org" itemscope>
    <span itemprop="organization-name">Manning Publications Co.</span>
    (<span itemprop="organization-unit">Hello! Series</span>)
  </p>
</section>

This is what it looks like with no styling applied. Although you could apply classes to various elements to attach styles, you can use the various item* attributes instead.

The simplest attribute selector is called the existence selector:

[itemscope] {
  outline: 4px dashed black;
}

When you put the attribute name inside square brackets, the selector will match any element that has the attribute.

Attribute selectors can be appended to other simple selectors. To select only paragraphs that have an itemscope attribute, use this selector:

p[itemscope] {
  outline: 4px dashed black;
}

Although attribute existence can be useful occasionally, it’s more likely you’ll be interested in selecting between attributes with values. The syntax for this is intuitive:

[itemprop="org"] {
  outline: 4px dashed black;
}

Note that three elements have an itemprop attribute that begins with the letters org, but only the one that exactly matches has been selected. It’s possible to select the elements whose attribute begins with org:

[itemprop^="org"] {
  outline: 4px dashed black;
  display: block;
}

Similarly, you can select all the elements whose itemprop attribute ends with a particular value:

[itemprop$="name"] {
  outline: 4px dashed black;
  display: block;
}

In the examples so far, the attribute value you’re trying to match is a simple string, so quotes are optional. You could also write this selector as [itemprop$=name]. If the value you’re matching contains characters other than letters and numbers, then the quotes are required.

If the significant part of the attribute value is in the middle rather than at the start or the end, there’s also an attribute selector for that:

[itemprop*="tion"] {
  outline: 4px dashed black;
  display: block;
}

This rule matches any element which has an itemprop property with a value which contains tion somewhere within it.

The traditional CSS ID selector can now be seen as syntactic sugar for the attribute selector. These two selectors are equivalent:

#myid                                 [id="myid"]

But the class selector is slightly more difficult. What attribute selector we’ve considered so far would be equivalent to .myclass? Let’s consider some options.

Attribute selector

Matches

Doesn’t match

[class="myclass"]
class="myclass"
class="myclass
       otherclass"
[class^="myclass"]
class="myclass
       otherclass"
class="otherclass
       myclass"
[class*="myclass"]
class="otherclass
       myclass"
class="notmyclass"
 

It’s clear that there’s a gap in our toolkit. Fortunately, CSS3 fills this hole: [class~="myclass"] selects an element with a whitespace-separated list of values, one of which is myclass.

Attribute selector

Matches

Doesn’t match

[class~="myclass"]
class="myclass"
class="myclass
       otherclass"
class="notmyclass"

Choosing what isn’t

So far, we’ve concerned ourselves with positive identification. We’ve selected the elements that are the first child, and we’ve selected elements that have a particular attribute. But CSS3 also gives us the ability to select elements that aren’t the first child or don’t have particular attributes, with the :not pseudo-class. To understand how this might be useful, consider how you might lay out a form:

<label>Text:
  <input type="text">
</label>
<label>Range:
  <input type="range">
</label>
<label>Radio:
  <input type="radio">
</label>
<label>Checkbox:
  <input type="checkbox">
</label>

It looks a little disorganized, so let’s add some styles to make things more consistent:

input {
  margin: 1em;
  display: block;
  width: 12em;
}

Clearly you want to apply different styles to input elements of type radio and checkbox. By selecting positively, you have two basic options: select everything and then override (following, left), or explicitly select only the items you want to style (following, right):

input {
  margin: 1em;
  display: block;
  width: 12em;
}
input[type=radio],
 input[type=checkbox] {
  display: inline;
  width: auto;
}
input { margin: 1em; }
input[type=text],
input[type=search],
input[type=tel],
input[type=url],
input[type=email],
input[type=password],
input[type=datetime],
input[type=date],
input[type=month],
input[type=week],
input[type=time],
input[type=datetime-local],
input[type=number],
input[type=range],
input[type=color],
input[type=file],
input[type=submit],
input[type=image],
input[type=reset],
input[type=button] {
  display: block;
  width: 12em;
}

The :not pseudo-class allows you to be more succinct than either of those two examples:

input { margin: 1em; }
input:not([type=checkbox]):not([
type=radio]) {
  display: block; width: 12em;
}

You can also combine :not with other selectors you’ve seen in this chapter. Going back to the :nth-child examples in the section “Selecting among a set of elements with pseudo-classes,” this is how you select everything except the first two list items:

li:not(:nth-child(-n+2)) {
  background-color: #000;
}

Pseudo-elements

Pseudo-elements are CSS selectors that allow you to style certain page elements as if an element existed in your markup. It sounds more complicated than it is, so let’s dive into some examples. A common typographical feature, almost since the beginning of book publishing, is to style the first line or first letter of a section differently than the following text. Following are some examples both from history and the present day.

Browser support quick check: pseudo-elements   :no ::first-letter/::first-line
1.0 1.0
3.0 3.0
5.5. 5.5
10.0 7.0
1.0 1.0

In order to achieve similar effects, CSS3 has the ::first-line and ::first-letter pseudo-elements. To examine these, we need some suitably weighty prose to live up to our historical antecedents. I’ve chosen a selection of quotes from Ada Lovelace all marked up as paragraphs like this:

<p>I never am really satisfied that I
understand anything; because, understand
it well as I may, my comprehension can
only be an infinitesimal fraction of all
I want to understand about the many
connections and relations which occur to
me, how the matter in question was first
thought of or arrived at, etc., etc.</p>

If you want to style the first line differently, what do you do? One option is to insert elements to signify the first line:

<p><span class="first">I never am
really</span> satisfied that I
understand anything; because,
understand  it well as I may, my
comprehension can only be an
infinitesimal fraction of all I want
to understand about the many
connections and relations which
occur to me, how the matter in
question was first thought of or
arrived at, etc., etc.</p>

This looks OK in the example, but what if the user’s screen is wider or narrower, or their font is larger, as in the following examples?

 

Pseudo-elements vs. pseudo-classes

Pseudo-elements create virtual elements within your document, as opposed to pseudo-classes, which rely on properties of the document entered by the author. In CSS3, pseudo-elements are distinguished by a double colon (::) rather than the single colon of a pseudo-class. This differs from CSS2, where both used a single colon.

 

The ::first-line pseudo-element puts the onus of calculating what constitutes the first line of text on the browser:

p::first-line {
  background-color: #000;
}

It applies styles as if there were an element wrapping all the text on the first line. But unlike a real element, you can’t style children of the first line. The pseudo-element can only come as the last simple selector in a selector group.

The ::first-letter pseudo-element is similar, except that it only selects the first letter:

p::first-letter {
  background-color: #000;
}

Although the background has been styled in this example because it stands out in the screenshots, it would be more common to use a decorative font for the first letter, or to increase its size.

Using both ::first-line and ::first-letter, it’s straightforward to create text that looks similar to the examples from the start of this section:

Choosing elements based on user interaction

Dynamic pseudo-classes allow you to assign different styles to elements based on user activity. One of the best known of these is the :hover pseudo-class, introduced in CSS2, which lets you apply a different style to an element when the mouse pointer is hovering over it (see appendix C for some examples). CSS3 adds several new dynamic pseudo-classes. In this section, you’ll learn about styling form elements based on their properties. This will let you give cues to your users about the state of form elements—for example, whether they’re required or whether they’re currently valid. After that, you’ll learn about the target selector that lets you style the page based on the current URL, which is useful for tabbed interfaces and slide shows.

Browser support quick check: dynamic pseudo-classes   Enabled/disabled/checked Valid/invalid/required Target
1.0 10.0 1.0
3.0 4.0 3.5
9.0 10.0 9.0
9.0 9.5 10.0
3.0 5.0 3.0

Styling form elements based on state

The first dynamic pseudo-classes we’ll consider are :enabled and :disabled. Here are two text inputs, one of which is disabled:

<label>Enabled
  <input type="text">
</label>
<label>Disabled
  <input type="text" disabled>
</label>

Form elements are enabled by default, so this rule targets the first input:

input:enabled {
  outline: 4px solid #000;
}

Most browsers make it fairly obvious when a form control is disabled, but the pseudo-classes allow you to add additional styling:

input:disabled {
  outline: 4px solid #000;
}

If your form enables and disables controls dynamically based on user input, then :enabled and :disabled allow you to attach transitions to the changes between the two states; see chapter 9 for further details.

The :checked and :indeterminate pseudo-classes can only be applied to inputs of type checkbox:

<label>Not checked
  <input type="checkbox">
</label>
<label>Checked
  <input type="checkbox" checked>
</label>

As you might expect, :checked lets you style all checked check boxes:

input:checked {
  outline: 4px solid #000;
}

You might use this to replace the default check box with a graphic.

The indeterminate state has to be set by a script:

input:indeterminate {
  outline: 4px solid #000;
}

Note that :indeterminate is independent of :checked—both checked and unchecked check boxes can be in the indeterminate state.

You can also use CSS3 with the HTML5 form features, such as validity. Here are one valid and one invalid form field:

<label>Valid
  <input type="url"
    value="http://manning.com">
</label>
<label>Invalid
  <input type="url"
    value="Not a URL">
</label>

The pseudo-class for valid inputs is, unsurprisingly, :valid:

input:valid {
  outline: 4px solid #000;
}

And the corresponding pseudo-class is invalid:

input:invalid {
  outline: 4px solid #000;
}

It’s also possible to style required inputs. Here are one required and one optional input (of course, inputs are optional by default):

<label>Required
  <input type="text" required>
</label>
<label>Optional
  <input type="text">
</label>

This is the CSS to select an input with the required attribute:

input:required {
  outline: 4px solid #000;
}

And this is the CSS to target just the optional input:

input:optional {
  outline: 4px solid #000;
}

Styling the page based on the target of the URL

Fragment identifiers—a string after a # symbol—are often used to identify sections within a long document, such as the table of contents at the top of a Wikipedia article. When the label in the fragment identifier matches an ID in the document, the browser scrolls the page down to where that element is displayed.

If the URL has a fragment identifier, then the element with the ID matching it can be given special styling with the :target pseudo-class. This is useful for slideshows and tab-based interfaces.

This example uses four paragraphs, each of which has an id attribute:

<p id="one">I never am really satisfied
that...</p>
<p id="two">In almost every computation
a...</p>
<p id="three">Many persons who are not
conversant...</p>
<p id="four">The Analytical Engine has
no pretensions...</p>

This is what the page looks like if you load it into your browser with a bare URL:

http://host/target.html

This CSS selector says, “Add a black background to the paragraph elements that are the target”:

p:target { background: #000; }

Now, if the URL is adjusted to contain a fragment identifier, the p:target rule is triggered. The following screenshots show the same page with two different fragment identifiers appended to the URL. When the fragment is #one, the element with id value one matches the p:target rule and has a black background.

You can adjust the CSS from the previous example so the paragraphs are hidden by default but visible when they’re the target:

p { display: none; }
p:target { display: block; }

Add a simple menu:

<menu>
    <a href="#one">Show one</a>
    <a href="#two">Show two</a>
    <a href="#three">Show three</a>
    <a href="#four">Show four</a>
</menu>

Initially all the tabs are hidden, so all you see is the menu and an empty space.

Clicking the Show Two link changes the URL to http://host/target.html#two. Now #two is the target. Thanks to the target selector, the element with id value two becomes display: block instead of display: none.

Clicking Show Four changes the target again: the element with an id value of four becomes visible.

Browser support

Browser support for CSS3 selectors is excellent across modern browsers. The main issue in browser support is the large numbers of people still using obsolete versions of Internet Explorer. As you’ll see, it’s easy to add support for these old browsers using j Query.

 
  12 14 4 6 8 9 10 11.1 11.5 5 5.1
Adjacent sibling
General sibling  
First/last child  
nth/last child  
Only child    
Of type  
Attribute
=
^=
*=
$=
~=
Not  
First letter
First line
Dis-/enabled    
In-/valid    
Checked
Indeterminate
Optional/required    
Target  
Key:
• Complete or nearly complete support
Incomplete or alternative support
Little or no support

Using jQuery to support older browsers

The jQuery JavaScript library uses CSS selectors as a key part of its normal operation. In order for this to work cross-browser, the authors of jQuery had to implement CSS selectors in JavaScript. This is handy if you want to use the latest CSS features but still present more limited older browsers with your intended design.

Here’s a CSS selector that doesn’t work in IE8 and older:

tbody tr:nth-child(2n+1) {
    background: #999;
}

The screenshot shows that in IE8, the odd rows don’t have the gray background that the rule specifies.

To add IE8 support without messing up your markup, you can add some jQuery. Start by adding the library itself:

<script src="jquery-1.5.2.min.js">
</script>

In an IE-only code block, use the jQuery selector engine to match the nodes using the same selector, and add a class to them:

<!--[if lte IE 8]>
<script>
$(document).ready(
  function() {
    $('tbody tr:nth-child(2n+1)')
      .addClass('odd');
  }
)
</script>
<style>
tr.odd { background: #999; }
</style>
<![endif]-->

All that’s now required is to replicate the style elements with that class. In most cases, you can add the selector to your original rule. But the nth-child syntax will cause IE8 to treat the whole rule as invalid, so the style rule also has to be replicated.

Summary

In this chapter, you’ve learned about many new features available in CSS3 for selecting elements: combinators for selecting elements based on relationships with their parents; pseudo-classes for selecting elements based on their relationships with their siblings; attribute selectors that reduce your dependence on class and id attributes; and dynamic pseudo-classes for giving immediate feedback to users on the state of form elements. It’s been a lot to get through, but these features make up the foundation on which all the rest of CSS is built.