27 June 2011
A good understanding of HTML and the basics of CSS, such as how to create a style rule and the role of CSS properties.
Intermediate
Note: You don't need specific software to write CSS. Any text editor will do. However, the code hints and the ability to see the results of your style rules in Live view make Dreamweaver CS5.5 a good choice. You should also download the sample files to test the examples in a variety of browsers.
A solid understanding of CSS selectors is essential not only for styling web pages, but also for working with jQuery. In Part 1 of this two-part tutorial series, you learned about the basic selectors supported by all browsers, including Internet Explorer (IE) 6, as well as attribute selectors that have been supported since the release of IE 7 in 2006. In this part, you'll learn CSS3 pseudo-classes and pseudo-elements. The CSS3 Selectors module has been a Proposed Recommendation since 2009, which means that it's very stable and widely supported by browsers. Firefox, Safari, Chrome, and Opera have supported CSS3 selectors for several years, and they're now supported by IE 9.
The CSS3 pseudo-classes allow you to style elements based on their position within the document hierarchy without the need to add custom classes to your HTML markup. For example, you can create styles for the first or last paragraph or list item. You can also style alternate rows in a table without worrying about the need to reassign classes when a new row is added to the table or the rows are sorted. Older versions of Internet Explorer simply ignore the new selectors, but you can use these selectors for progressive enhancement, improving the look of your web pages in modern browsers.
One of the first CSS techniques most web designers learn is how to style links using the :link , :visited , :hover , and :active pseudo-classes. They're called pseudo-classes because you don't add a class name to the opening <a> tag. The style is applied automatically depending on the current state of the link. The CSS3 pseudo-classes take this concept much further, automatically applying styles to elements depending on their position in the page structure. There are also pseudo-classes to style form elements depending on their current state (enabled, disabled, or checked). You can even style elements based on negative characteristics. For example, you can apply a style to every column in a data table except the first one. The great advantage of using these pseudo-elements is that you don't need to add classes to your HTML markup. Consequently, if you make changes to the page's content, you don't need to reassign all the classes. Let's say you have used a pseudo-class to apply a different style to the first paragraph in a sidebar. If you add a new paragraph above the existing first paragraph, the pseudo-class is automatically applied to the new first paragraph. This is particularly powerful when page content is generated or updated dynamically.
Let's begin by looking at pseudo-classes that affect the first, last, or only instances of the selected element.
There are six pseudo-classes in this category, namely:
:first-child:last-child:only-child:first-of-type:last-of-type:only-of-typeThe :first-child pseudo-class actually belongs to CSS2.1, and is supported by all browsers except IE 6; but I have included it here because it logically belongs with the others. Each of these pseudo-classes applies to siblings—in other words, elements that are at the same level of the document hierarchy. The difference between the "child" and "of-type" pseudo-classes lies in the relationship of the target element to its parent. The :first-child pseudo-class applies to the first element nested inside its parent, whereas the :first-of-type applies the first element of that particular type within its parent. The following examples should make the distinction clearer (the code is in children.html in the example files):
<div id="sidebar">
<h3>The Pleasures of London</h3>
<p>Integer turpis arcu, . . .</p>
<blockquote>
<p>No, Sir, when a man is tired of London,
he is tired of life; for there is in London
all that life can afford.</p>
</blockquote>
<h3>What to Do in London</h3>
<p>Donec eu mi sed turpis. . .</p>
</div>
In this block of code, the top <h3> heading is the first child of the sidebar <div> . So, you could apply a style to it using the :first-child pseudo-class like this:
h3:first-child {
font-variant:small-caps;
}
This style rule affects only the first <h3> heading. Although the second <h3> heading is also a child of the same <div> , the :first-child pseudo-class applies only to the first one. What's more, if you add anything inside the <div> before the first heading, the new item becomes the first child, so the heading would no longer be affected by the style.
As you might expect, the :last-child pseudo-class applies to the final child element. So, to apply a border to the bottom of the final paragraph in the sidebar, you could create the following style rule:
#sidebar p:last-child {
border-bottom: 3px #000 solid;
padding-bottom: 10px;
}
Although this works, it applies the border not only to the final paragraph in the sidebar, but also to the paragraph in the <blockquote> (see Figure 1).
This happens because the paragraph inside the <blockquote> is also the last child, albeit of a different parent. One way to prevent this style rule from affecting the <blockquote> is to use a child selector (see "Selectors supported by all visual browsers except IE 6" in Part 1 of this tutorial series) like this:
#sidebar > p:last-child {
border-bottom: 3px #000 solid;
padding-bottom: 10px;
}
Adding the greater-than sign makes the selector look only for a paragraph that is not only a direct child of the sidebar <div> , but is also its last child. As a result, the paragraph inside the <blockquote> no longer has a bottom border.
The :only-child pseudo-class works in a similar way. It targets elements that are the only child of their parent. The <blockquote> contains an only child, which can be styled like this:
blockquote p:only-child {
background-color: #CCC;
border-radius: 8px;
padding: 10px;
}
This adds a background to the paragraph, as shown in Figure 2.
However, if you add a second paragraph (or any other element) inside the <blockquote> , the style no longer applies (see Figure 3).
Because the :first-child , :last-child , and :only-child pseudo-classes are very specific, you need to be careful how you use them. Once an element is no longer the first, last, or only child of its parent, the styles no longer apply.
The "of-type" pseudo-classes are more flexible. The code in of_type.html contains the following unordered list:
<ul id="nav">
<li><a href="#">Home</a></li>
<li><a href="#">Rooms</a></li>
<li><a href="#">Dining</a></li>
<li><a href="#">Gardens</a></li>
<li><a href="#">Reservations</a></li>
</ul>
The list has been styled as a menu bar with a white right border acting as a separator, but this looks strange on the last item (see Figure 4).
Using the :first-of-type and :last-of-type pseudo-classes, you can not only deal with the problem of the unwanted border, but you can also add rounded corners to each end of the menu bar like this:
#nav li:first-of-type a {
border-radius: 12px 0 0 12px;
}
#nav li:last-of-type a {
border-radius: 0 12px 12px 0;
border-right: none;
}
This produces the result shown in Figure 5.
The beauty of using pseudo-classes is that these styles are applied automatically to the first and last items. So, if you remove an item from the unordered list or add a new one, there's no need to adjust the style rules. The browser handles it for you.
The :only-of-type pseudo-class works the same way. It applies to an element that has no siblings of the same type. One potential use is in a page that displays a dynamically generated ordered list. If the list contains only one item, you can suppress the number like this:
ol li:only-of-type {
list-style: none;
}
CSS3 pseudo-classes give you even greater control over selecting elements according to their position in the document hierarchy through the nth-type pseudo-classes. Four pseudo-classes fall into this category, namely:
:nth-child():nth-last-child():nth-type():nth-last-of-type()To use these pseudo-classes, you pass an argument to the parentheses indicating the position in the series that you want to select. The argument can be a number, a keyword, or a formula. Using either a number or keyword is simple. Understanding the formula is a little more complicated.
Let's begin by using a number. Passing a number to one of these pseudo-classes simply selects the element at that position in the series. For example, this selects the second paragraph within its parent element:
p:nth-type(2)
The nth-last pseudo-classes count from the end of the parent element. So, use this to select the penultimate paragraph:
p:nth-last-of-type(2)
The two keywords that you can use with these pseudo-classes are odd and even . This selects every odd-numbered row in a table:
tr:nth-child(odd)
If you add or remove a row from the table, the browser automatically adjusts the styles. This is a huge time-saver for adding a different background color to alternate table rows.
The nth-type pseudo-classes also let you select a recurring sequence of elements, such as every fourth table row, by using the formula an+b , in which a and b are numbers and n is the literal character. The simple way to understand the formula is to treat n as zero and increment it by one throughout the series. For example, tr:nth-child(4n+1) selects the first, fifth, and ninth table rows like this:
(4 x 0) + 1 = 1
(4 x 1) + 1 = 5
(4 x 2) + 1 = 9
Similarly, tr:nth-child(4n+2) selects the second, sixth, and tenth rows:
(4 x 0) + 2 = 2
(4 x 1) + 2 = 6
(4 x 2) + 2 = 10
Figure 6 shows a table that has been styled using nth-type pseudo-classes (it's nth-type.html in the example files).
The style sheet for nth-type.html contains the following rules:
th {
background-color:#046380;
color:#EFECCA;
padding:3px 10px;
text-align:right;
}
tr:nth-child(1) th {
text-align:center;
vertical-align:top;
font-variant:small-caps;
}
th:nth-of-type(1) {
width:8%;
}
tr:nth-child(4n+1) {
background-color:#F8EAC5;
}
tr:nth-child(4n+2) {
background-color:#D8D0AC;
}
tr:nth-child(4n+3) {
background-color:#EFECCA;
}
tr:nth-child(4n+4) {
background-color:#D5D8AC;
}
The th style rule aligns the text in all table header cells on the right, but the following selector, tr:nth-child(1) th applies different styles to the headers in just the first row.
The next selector, th:nth-of-type(1) selects the first header in each table row—in effect, the first column—and sets its width to 8%. Finally, the an+b formula sets four different styles that are applied in sequence to the table rows. Using four different background colors is probably over the top for this table, but it demonstrates how the formula works in practice.
Note: I could have used tr:first-child th instead of tr:nth-child(1) because :nth-child(1) and :first-child have exactly the same meaning. Similarly, th:nth-of-type(1) could be replaced by th:first-of-type . In fact, I could have used th:first-child in this example, because the table headers are the first child of each row. Sometimes, the meanings of pseudo-elements overlap.
There are two pseudo-classes that select elements based on negative factors:
:not():emptyTo use the :not() pseudo-class, you place a simple selector between the parentheses to exclude all matching elements from the selection. For example, the following selector styles all table rows, except the first:
tr:not(:first-child)
Similarly, the following selector styles all table cells, except the last one in each row:
td:not(:last-child)
The :empty pseudo-class, on the other hand, selects elements that are completely empty. The definition of empty is very strict: the element must contain nothing between the opening and closing tags—not even a space.
Both pseudo-classes were used to style the table in negative.html (see Figure 7).
The relevant styles look like this:
tr:not(:last-child) > td {
border-bottom: 1px solid #222;
}
td:not(:last-child) {
border-right: 1px solid #222;
}
tr:not(:first-child) > th {
text-align:left;
}
td {
background-color:#FFFDCE;
text-align:right;
}
td:empty {
background-color:#D8F2D7;
}
The first style applies a border to the bottom of each table row except the last, while the second one applies a border to the right of each table cell except the final one in each row. This ensures that the table border is applied to the cells at the bottom and on the right.
The third style targets all table header cells, except those in the first row. As a result, the table headers in the first row are centered, while those in the subsequent rows are left-aligned.
Finally, td:empty applies a different background color to the empty table cells.
Note: By default, Dreamweaver inserts a non-breaking space ( ) into empty table cells. You must delete this manually for the :empty pseudo-class to work.
By the way, if you're thinking that you won't be able to use these pseudo-classes for years because they're not supported by older versions of Internet Explorer, take a look at Figure 8, which shows negative.html in IE 7 on Windows XP. It's not as nicely styled, but the content remains perfectly accessible.
Three pseudo-classes select form elements based on their state, namely:
:disabled:enabled:checkedThe :disabled pseudo-class is applied to all form elements that have the disabled attribute in their HTML tag. There's no equivalent enabled attribute, but the :enabled pseudo-class automatically applies to any form element that hasn't been disabled. The :checked pseudo-class applies to elements that have the checked attribute in their HTML tag. It's also toggled on and off automatically if a radio button or check box is selected or deselected.
Some browsers prevent you from styling form elements, so you need to check the effect of your styles carefully when using these pseudo-classes.
It's common to link to a specific part of a page using an ID or a named anchor. The :target pseudo-class allows you to draw attention to the section of a page that has been accessed in such a way. The style is applied only when the page is loaded with a URL that ends with a hash sign ( # ) followed by the ID or anchor name. At all other times, the style is ignored.
A simple example of the :target pseudo-class in action can be found in target.html in the example files. The page contains Shakespeare's sonnets #110–116. The heading for each sonnet has the ID sonnetXXX , where XXX represents the number. A list of links at the top of the page takes you directly to the relevant sonnet. Load the page into a browser and scroll down to the bottom. The final section of the page looks like Figure 9.
Scroll back to the top of the page, and click the link for Sonnet 116 ("Let me not to the marriage of true minds"). This time, the heading should have a pale green background (see Figure 10).
The style rule that adds the highlighting looks like this:
h2:target {
background-color:rgba(0,102,51,0.2);
padding: 3px;
}
Scroll back to the top of the page, and click the link for Sonnet 115 ("Those lines that I before have writ do lie"). The highlighting from the heading for Sonnet 116 has disappeared, but Sonnet 115 is now highlighted, as shown in Figure 11.
Using this technique is particularly useful for linked targets that are close to the bottom of the page. Although it's not supported by older browsers, this is a good example of progressive enhancement.
The CSS3 Selectors module contains four pseudo-elements, all of which have been inherited from CSS2.1, and which were described in Part 1 of this tutorial series. The only difference is that CSS3 precedes pseudo-elements with a double colon like this:
:first-letter becomes ::first-letter:first-line becomes ::first-line:before becomes ::before:after becomes ::afterThe idea is to distinguish between pseudo-classes and pseudo-elements. The distinction is rather tenuous and is made even more so by the decision to continue to support the original single-colon versions for backwards compatibility. In fact, to support IE 7 and IE 8, you must use the single-colon versions. However, work has already begun on CSS4, with proposals to add new pseudo-elements, such as ::first-words() and ::nth-line() . If and when they're adopted, you will need to use double-colons with them. But that's unlikely to happen in the immediate future.
That concludes this two-part tutorial series on CSS selectors. The pseudo-classes covered in this second part are not supported by IE 6, IE 7, and IE 8, but they're fully supported by all other browsers (including IE 9 and later). They're worthwhile introducing into your style sheets for progressive enhancement—improving the user experience for anyone using the most recent version of a browser.
You can find out more about CSS selectors from the following resources:
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.
Tutorials and samples |
| 04/23/2012 | Resolution/Compatibility/liquid layout |
|---|---|
| 04/20/2012 | using local/testing server with cs5 inserting images look fine in the split screen but do not show |
| 04/18/2012 | Ap Div help |
| 04/23/2012 | Updating |