CSS 2.1 selectors, Part 3
This is the third and final part of a three-part article series that explains the selectors that are available in CSS 2.1. Part 1 is about the more basic stuff like type selectors, class and id selectors, the universal selector, simple selectors. In Part 2 I explained combinators, combined selectors, grouping, and attribute selectors.
This time I will take a closer look at pseudo-classes and pseudo-elements. Like the more advanced selectors I talked about in Part 2, pseudo-classes and pseudo-elements are not yet fully supported in all major browsers, so remember checking what happens when support is missing. You don’t want your content to be inaccessible in browsers that don’t support the CSS described here.
Pseudo-classes and pseudo-elements
Pseudo-classes and pseudo-elements can be used to format elements based on information that is not available in the document tree. For example, there is no element that refers to the first line of a paragraph or the first letter of an element’s text content.
Pseudo-classes
Pseudo-classes match elements based on characteristics other than their name, attributes or content.
:first-child
This pseudo-class matches an element that is the first child element of another element. Let’s say you want to give the first paragraph of an article a special styling. If the article is contained in a div element with a class name of “article”, the following rule would match the first p element in each article:
div.article p:first-child {font-style:italic;}
To match all p elements that are the first child of any element, you can use the selector in this rule:
p:first-child {font-style:italic;}
:link and :visited
The link pseudo-classes affect the unvisited and visited states of links. The two states are mutually exclusive – a link cannot be both visited and unvisited at the same time.
These pseudo-classes only apply to hyperlink source anchors as determined by the document language. For HTML, this means a elements with an href attribute. Since it doesn’t affect any other elements, the following selectors are the same:
a:link:link
:hover, :active, and :focus
The dynamic pseudo-classes can be used to control the presentation of certain elements depending on certain actions performed by the user.
:hover applies while the user is using a pointing device to point to an element but does not activate it. Most commonly this means using a mouse to make the cursor hover over an element.
:active applies while an element is being activated by the user. For mouse users this means if you press the mouse button and keep it pressed, until you release it.
:focus applies while an element has the focus, i.e. while it accepts keyboard events.
An element may match several pseudo-classes at the same time. An element could have focus and be hovered over, for instance:
input[type=text]:focus {color:#000;background:#ffe;}input[type=text]:focus:hover {background:#fff;}
The first rule will match single line input elements that have focus, and the second rule will match the same elements when they are also hovered over.
:lang
The language pseudo-class can be used to style elements whose content is defined to be in a certain language (human language, not markup language). The following rule defines which quotation marks to use for an inline quotation that is in Swedish:
q:lang(sv) { quotes: "\201D" "\201D" "\2019" "\2019"; }
The human language of a document or element is normally specified with the lang attribute in HTML and the xml:lang attribute in XHTML.
Pseudo-elements
Pseudo-elements allow authors to access and format parts of the document that are not available as nodes in the document tree.
:first-line
The :first-line pseduo-element affects the first line of a paragraph of text. It can only be applied to block level elements, inline-block, table-caption or a table-cell.
The length of the first line obviously depends on a number of factors, including font size and the width of the element containing the text.
The following rule will apply to the first line of text in a paragraph:
p:first-line {font-weight:bold;color;#600;}
Note that there are some restrictions on which properties that apply to a :first-line pseudo-element. See The :first-line pseudo-element for a list of the properties that apply.
:first-letter
This pseudo-element lets you target the first letter or digit of an element, and applies to block, list-item, table-cell, table-caption and inline-block elements.
The following rule would apply to the first character in an element with the class name “preamble”:
.preamble:first-letter {font-size:1.5em;font-weight:bold;}
As for the :first-line pseudo-element, the :first-letter pseudo-element has some restrictions on which properties that can be applied. See The :first-letter pseudo-element for a list of the properties that apply.
:before and :after
Among the more debated CSS features, the :before and :after pseudo-elements can be used to insert generated content before or after an element’s content.
Here is an example of how :before can be used (from my article Custom borders with advanced CSS):
.cbb:before {content:"";display:block;height:17px;width:18px;background:url(top.png) no-repeat 0 0;margin:0 0 0 -18px;}
An example of using :after to insert the URL of a link after the link text:
a:link:after {content: " (" attr(href) ") ";}
Internet Explorer problems
Before you start putting everything you’ve learned about selectors to use, keep in mind that Internet Explorer up to and including version 6 has incomplete support for CSS 2.1 selectors. The following are unsupported or problematic:
- Child selectors
- Adjacent sibling selectors
- Attribute selectors
- Multiple class selectors
- The
:first-childpseudo-class - The language pseudo-class
- The
:beforeand:afterpseudo-elements - The
:hoverpseudo-class only works onaelements - The
:focuspseudo-class isn’t supported. Foraelements that have focus, the:activepseudo-class is applied.
Fortunately, it looks like Internet Explorer 7 will have complete support for CSS 2.1 selectors.
You’ve got the power – now use it right
And that’s all. Now that you’ve learned all about selectors in CSS 2.1, you’ve got a whole lot of power to use when styling your documents. Use it with care, to keep your markup tidy, and to increase accessibility and usability. And remember to think about what happens in older browsers that don’t support the more advanced CSS selectors.
Translations
This article has been translated into the following languages:
- Brazilian Portuguese: Seletores CSS 2.1 Parte 3 (Translation by Mauricio Samy Silva)
- Chinese: [译稿]细说CSS样式选择符(一)——CSS 2.1 Selectors, [译稿]细说CSS样式选择符(二)——CSS 2.1 Selectors, [译稿]细说CSS样式选择符(三)——CSS 2.1 Selectors
- Dutch: CSS 2.1 Selectors, deel 3 (Translation by Arjan Snaterse)
- French: Sélecteurs CSS 2.1, partie 3 (Translation by Manuel Catez)
- Polish: Selektory CSS 2.1 - część 3 (Translation by Łukasz Adamczuk)
- Previous post: Character references in HTML and XML
- Next post: Colour blindness simulator for Mac OS X
Information, sponsorship, and externals
About the author
Roger Johansson is a Swedish web professional specialising in web standards, accessibility, and usability. More about me and this site.
Latest articles
- Validation statistics from Nikita the Spider Comments off
- An analysis of the sites crawled by the bulk validation tool Nikita the Spider during March 2008.
- Authentic Jobs API and Affiliates program Comments off
- The Authentic Jobs job listing service now has a public API and an affiliate program.
- What does Acid3 mean to you and me? Comments off
- Opera and Apple have announced that their web browsers pass the Acid3 Browser Test, but how will that help web designers and developers?
- Designing Web Navigation (Book review) Comments off
- Learn the fundamentals of navigation design and design better navigation systems for large and small sites as well as for web based applications.
- DOMAssistant bundle for TextMate Comments off
- To save keystrokes and speed up development I have created a DOMAssistant bundle for TextMate.
- First impressions of Internet Explorer 8 Beta 1 Comments off
- My impressions after trying out Internet Explorer 8 Beta 1 for a couple of days.









Comments
Another great addition to add to my readables behind my desk. Thanks for the good wrap-up!
Great article. Useful, and yet very understandable. Thanks for the helpful info.
You should also mention that the :hover pseudo-class only works for a-elements in IE.
Bza: Thanks, I updated the list of IE problems.
Something to add:
Opera 8 supports most of the peusdo elements and classes but not all. One I've noticed is that it does not support :last-child, it does support :first-child however.
Really made me clearer on the topic, thanks.
This is just the reason I subscribe to your RSS! Thanks for the heads up!
Jason G: I believe :last-child is a CSS3-feature, and this guide is about CSS2.1-selectors.
Yes a great series Roger and one I'll keep as a reference. I've learned a few things as well. Thanks.
What is the meaning of the backticks (`) in the :focus examples?
Scott: The backticks were typos and weren't supposed to be there. Fixed now. Thanks :-).
Great three-part article series. Thx!
re: backticks
Whew! I thought that perhaps I was seeing some funky new syntax that I couldn't find a reference to. ;-)
Yeah, I'll have to agree. Great article (series). When the first part was written I was kind of new to all this, but since then I have learned a lot so now this is perfect as references.
So how does one go about implementing those "advanced" selectors that IE6 (and below) does not support in our every day projects?
I want to learn and use them, but since all my web work has to work in IE, it hinders using them. And really, even with IE7 on the horizon, IE6 will be around for another 7 or so years before it can be safely abandoned.
How do we make the transition without doubling the workload?
you're joking with the 7 years, right? I'd say that the pace of all things web related has increased, and if you look 7 years back there was... dunno, IE 5.0 and netscape 4.75? Do you still support both of them? I would guess that, with all auto updates and big hype around IE7, in 1, maximum 2 years down the line the average statistics will have moved one version up, with IE5.0 and 5.5 together at maybe 1%? Or am I too optimistic?
I found your description of :first-child interesting for two reasons. Firstly, my information seemed to suggest that "div:first-child" would select the first child of the div but, assuming Opera 9TP and FF1.5B2 are correct, in fact "div:first-child" means that div must be the first child of its parent.
This brings me to the second observation in that this pseudo-class is unique in that it reverses the direction of CSS searching. For example, using the selector "p a", you look for a "p" then you look for "a" within it. However, with a:first-child, you look for an "a", then you reverse your search to see if there are any "a" before it but within the same parent.
There is another way to create the same styling for browsers that support the adjacent selector but not the :first-child pseudo-class. For example, let's say that you wanted the first paragraph in a div to be colored blue but all other paragraphs red. You could use "div p {color:blue}" to colour all "p" within a div blue and then use "div p+p {color:red}" to color the second and following "p" red. Of course, this doesn't help IE users because IE doesn't support the adjacent selector.
Use Dean's Edwards IE7 for upcoming 1-2 years. ( http://dean.edwards.name/IE7/ ) It is really good solution for future, which allow us write clean CSS almost without hacks.
Matthias - Yes, I was being a bit sarcastic with the 7 years. But, even with all the hype of IE7, your regular, "I only use the computer to browse the internet", will not think to or even know how to upgrade their browser. Who knows how long it'll be.
Fatal, I've seen Dean Edwards IE7 before but never really researched it. It doesn't create any noticeable overhead does it since it uses a bunch of javascript to "fix" IE?
It's also worth noting that the :hover selector will only work on a elements with an href attribute. Take that off your link and it stops working... Not a common problem but it occasionally arises with dynamically generated anchors.
Last two versions are very good (0.8, 0.9). There is couple of problems.
First problem if you have veeeery long pages with sooo advanced styling (it can take 2-5 of seconds to "render" for IE7).
Second problem (for current version 0.9) is when you using DOM scripting and don't want to refresh styles for whole page. My thought that Dean already working on this issue...
So, for static or almost static average pages Dean's IE7 is OK. I use it and I like it. One more time thank's to Dean.
Jules: Pseudo-classes select an element based on its state or condition. By the definition of a pseudo-class, it can't select any element other than the one it's attached to. That is, if you see "element:pseudo-class", that part of the selector can't possibly select anything but the element. If you're looking to select the first child of the div, you should do "div > *:first-child".
Not quite true, Mike. Opera 7+, NN 7+, FF1+ and Moz (tested 1.7) all support the :hover on a elements with no href present. It's IE only that exhibits this.
Note: I've not tested the Mac browsers to know if this holds true for them.
Cheers for the write-up Roger. Jeff
Nanobot wrote:
Good explanation, many thanks.
Jeff: All Mac browsers except IE support :hover on a elements without an href attribute.
There's something I recently noticed with the use of pseudo-classes on "a"-elements: IE does not support the ":focus"-pseudo-class (at least not on "a"-elements). Instead IE seems to be applying ":active"-css-rules when the "a"-element is in focus (e.g. when switching through links on the page with the "tab"-key).
I only tested that with 2 simple links in IE6/Win... but I think that is reason enough to mention it. Fx1+ should apply the ":focus"-rules and not the ":active"-rules when tabbing through the links (it does on my Fx1.0.7. I don't have other versions runnning).
Or am I completely off here?...
Johan: Correct, IE/Win applies :active instead of :focus to focused links, and I should mention it in the article.
Very helpful. Thanks a bunch. :)olc
Sorry, comments are closed for this post.