Pseudo-Classes and Pseudo-Elements

Sometimes you need to select parts of a web page that don't have tags per se, but are nonetheless easy to identify, like the first line of a paragraph or a link as you move your mouse over it. CSS gives you a handful of selectors for these doohickeys—pseudo-classes and pseudo-elements.

Four pseudo-classes let you format links in four different states based on how a visitor has interacted with that link. They identify when a link is in one of the following four states:

Chapter 9 shows you how to design links using these selectors to help your visitors click their way around your site.

The typographic features that make books and magazines look cool, elegant, and polished didn't exist in the early web era. (After all, when did scientists ever worry about looking cool?) CSS provides two pseudo-elements—:first-letter and :first-line—that give your web pages the design finesse that print has enjoyed for centuries.

The :first-letter pseudo-element lets you create a drop cap—an initial letter that jumps out from the rest of the paragraph with bigger or bolder font formatting, as at the beginning of a book chapter.

Styling the :first-line of a paragraph in a different color keeps your reader's eye moving and makes text appear appealing and fresh. (If you're intrigued, Chapter 6 is all about formatting text, and Formatting the First Letter or First Line of a Paragraph covers these two pseudo-elements in depth.)

The CSS guidelines define several powerful pseudo-class and -element selectors besides the ones covered so far. Unfortunately, the still-common Internet Explorer 6 doesn't recognize them. So most web surfers can't appreciate any design elements you create with these selectors (at least until they upgrade to IE 8 or switch to Firefox or Safari—or trade in their PCs for Macs). Meanwhile, you can work around this problem using JavaScript, as described in the box on :first-child.

The :before pseudo-element does something no other selector can: It lets you add content preceding a given element. For example, say you wanted to put "HOT TIP!" before certain paragraphs to make them stand out, like the boxes in this book that say "UP TO SPEED" and "POWER USERS' CLINIC." Instead of typing that text in your page's HTML, you can let the :before selector do it for you. This approach not only saves on code, but also if you decide to change the message from "HOT TIP!" to, say, "Things to know," then you can change every page on your site with one quick change to your style sheet. (The downside is that this special message is invisible to browsers that don't understand CSS or don't understand the :before selector.)

First, create a class (.tip, say) and apply it to the paragraphs that you want to precede with the message, like so: <p class="tip">. Then, add your message text to the style sheet:

p.tip:before {content: "HOT TIP!" }

Whenever a browser encounters the .tip class in a <p> tag, it dutifully inserts the text "HOT TIP!" just before the paragraph.

The technical term for text you add with this selector is generated content, since web browsers create (generate) it on the fly. In the page's HTML source code, this material doesn't exist. Whether you realize it or not, browsers generate their own content all the time, like the bullets in bulleted lists and numbers in ordered lists. If you want, you can even use the :before selector to define how a browser displays its bullets and numbers for lists.

Neither IE 6 nor IE 7 understand the CSS content property, so you probably won't see wide use of the :before or :after (discussed next) pseudo-elements. However, Internet Explorer 8 and all other major browsers do, so you'll find full instructions for using it on content in Chapter 16.

Exactly like the :before selector, the :after pseudo-element adds generated content—but after the element, not before. You can use this selector, for example, to add closing quotation marks (") after quoted material.

Going back to the HTML family tree analogy for a moment, recall what a child tag is: any tag directly enclosed by another tag. (For example, in Figure 3-5, <h1>, <p>, <h2>, and <ul> are all children of the <body> tag.) The :first-child pseudo-element lets you select and format just the first of however many children an element may have.

A <ul> tag, for example, which creates a bulleted list, can have many list items as children. (In Figure 3-5, the <ul> tag has three <li> children.) To format just the first list item (in boldface), you can write this rule:

li:first-child { font-weight: bold; }

Because the :first-child selector includes only the name of the child element, never the parent, this style formats any <li> tag that's the first child of any other tag, not just <ul>. List items always fall within lists, so you know the selector li:first-child affects all lists on the page—unordered or ordered. With other tags, however, the :first-child selector gets a little tricky. For example, in Figure 3-5, the selector p:first-child would have no effect at all, since the <p> tag is a child of the <body> tag, but it isn't the first child—the <h1> tag is.

Since the HTML parent-child relations can change each time you edit a web page, it's hard to predict how the :first-child selector will behave as you develop your website. Also, this selector doesn't work at all in Internet Explorer 6 or earlier versions—another reason to avoid it unless you've got a really good use for it.

The :focus pseudo-class works much like the :hover pseudo-class. While :hover applies when a visitor mouses over a link, :focus applies when the visitor does something to indicate her attention to a web page element—usually by clicking or tabbing into it. In programmery lingo, when a visitor clicks in a text box on a web form, she puts the focus on that text box. That click is a web designer's only clue as to where the visitor is focusing her attention.

The :focus selector is mostly useful for giving your visitor feedback, like changing the background color of a text box to indicate where he's about to type. (Single-line text fields, password fields, and multi-line <textarea> boxes are common targets for the :focus selector.) This style, for example, adds a light yellow color to any text box a visitor clicks or tabs into:

input:focus { background-color: #FFFFCC; }

The :focus selector applies only while the element's in focus. When a visitor tabs into another text field or clicks anywhere else on the page, she takes the focus—and the CSS properties—away from the text box. Unfortunately, neither IE 6 nor IE 7 understand the :focus selector, but you can still use it to add visual interest or highlight form fields for other browsers. (IE 6 and 7 won't know what they're missing, and you don't have to tell them.)