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 match elements based on characteristics other than their name, attributes or content.


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:

  1. div.article p:first-child {
  2. font-style:italic;
  3. }

To match all p elements that are the first child of any element, you can use the selector in this rule:

  1. p:first-child {
  2. font-style:italic;
  3. }

: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:

  1. a:link
  2. :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:

  1. input[type=text]:focus {
  2. color:#000;
  3. background:#ffe;
  4. }
  5. input[type=text]:focus:hover {
  6. background:#fff;
  7. }

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.


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:

  1. 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 allow authors to access and format parts of the document that are not available as nodes in the document tree.


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:

  1. p:first-line {
  2. font-weight:bold;
  3. color;#600;
  4. }

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.


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”:

  1. .preamble:first-letter {
  2. font-size:1.5em;
  3. font-weight:bold;
  4. }

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):

  1. .cbb:before {
  2. content:"";
  3. display:block;
  4. height:17px;
  5. width:18px;
  6. background:url(top.png) no-repeat 0 0;
  7. margin:0 0 0 -18px;
  8. }

An example of using :after to insert the URL of a link after the link text:

  1. a:link:after {
  2. content: " (" attr(href) ") ";
  3. }

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-child pseudo-class
  • The language pseudo-class
  • The :before and :after pseudo-elements
  • The :hover pseudo-class only works on a elements
  • The :focus pseudo-class isn’t supported. For a elements that have focus, the :active pseudo-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.


This article has been translated into the following languages:

Posted on October 24, 2005 in CSS


  1. Another great addition to add to my readables behind my desk. Thanks for the good wrap-up!

  2. Great article. Useful, and yet very understandable. Thanks for the helpful info.

  3. You should also mention that the :hover pseudo-class only works for a-elements in IE.

  4. October 24, 2005 by Roger Johansson (Author comment)

    Bza: Thanks, I updated the list of IE problems.

  5. 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.

  6. Really made me clearer on the topic, thanks.

  7. This is just the reason I subscribe to your RSS! Thanks for the heads up!

  8. October 25, 2005 by Michael Odden

    Jason G: I believe :last-child is a CSS3-feature, and this guide is about CSS2.1-selectors.

  9. Yes a great series Roger and one I’ll keep as a reference. I’ve learned a few things as well. Thanks.

  10. What is the meaning of the backticks (`) in the :focus examples?

  11. October 25, 2005 by Roger Johansson (Author comment)

    Scott: The backticks were typos and weren’t supposed to be there. Fixed now. Thanks :-).

  12. Great three-part article series. Thx!

  13. re: backticks

    Whew! I thought that perhaps I was seeing some funky new syntax that I couldn’t find a reference to. ;-)

  14. October 25, 2005 by Teddy

    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.

  15. 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?

  16. 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?

  17. 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.

  18. October 26, 2005 by FataL

    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.

  19. 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?

  20. 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.

  21. October 27, 2005 by FataL

    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.

  22. 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”.

  23. October 28, 2005 by Jeff Home

    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 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

  24. Nanobot wrote:

    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.

    Good explanation, many thanks.

  25. October 28, 2005 by Roger Johansson (Author comment)

    Jeff: All Mac browsers except IE support :hover on a elements without an href attribute.

  26. 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?…

  27. November 18, 2005 by Roger Johansson (Author comment)

    Johan: Correct, IE/Win applies :active instead of :focus to focused links, and I should mention it in the article.

  28. Very helpful. Thanks a bunch. :)olc

Comments are disabled for this post (read why), but if you have spotted an error or have additional info that you think should be in this post, feel free to contact me.