CSS 2.1 selectors, Part 1

Among the first things you learn about when you start out with CSS are selectors. Selectors are obviously a fundamental part of CSS, but few developers use them to their full potential. While you can get a lot done with just the type, ID, and class selectors, there are many more.

Learning how to use the full range of CSS selectors available in CSS 2.1 properly can actually help you keep your HTML a lot cleaner. It will let you minimise unnecessary use of the class attribute and the need for adding extraneous div and span elements to the markup. Sounds good, right?

So why isn’t the full range of selectors in wide use? The most important reason has been insufficient support in Internet Explorer up to and including version 6. All other recent browsers support most or all CSS 2.1 selectors. Be aware of that before rushing out to use everything that is described in this series.

The good news is that Internet Explorer 7 will have much better support for selectors. Knowing that you will be able to put them to good use in the future, now is as a good a time as any to learn about the full range of selectors that are available.

Since there are so many CSS selectors, a single article explaining them all would become very long. To make the information easier to digest I have split this into three parts:

  1. Part 1, this article, explains the basics of selectors plus the universal, type, id, and class selectors.
  2. Part 2 is about combinators, combined selectors, grouping, and attribute selectors.
  3. Part 3 will be all about pseudo-classes and pseudo-elements.

I will post the articles over a couple of weeks and update each of them with links to the other parts as they are published.

Right then. Let’s get started.

Selector basics

First the very basics. A CSS selector is made up of a pattern that is matched against all elements in the document tree. When all conditions in the pattern are true, the selector matches and the declarations within the rule are applied to the element or elements that match. Consider this very simple CSS rule:

  1. p { color:#f00; }

The selector is the part of a CSS rule that comes before the opening curly brace, “{“. The selector here is p, which will match all p elements in the document and make any text they contain red. Very basic.

Selector overview

Ok, that was a really simple example. I’m going to describe all the other selectors later on, so things will definitely get a bit trickier. Before that though, here is an overview of the syntax for all CSS 2.1 selectors (based on the table in CSS 2.1, 5.1 Pattern matching):

Overview of CSS 2.1 selector syntax
Selector type Pattern Description
Universal * Matches any element.
Type E Matches any E element.
Class .info Matches any element whose class attribute contains the value info.
ID #footer Matches any element with an id equal to footer.
Descendant E F Matches any F element that is a descendant of an E element.
Child E > F Matches any F element that is a child of an E element.
Adjacent E + F Matches any F element immediately preceded by a sibling element E.
Attribute E[att] Matches any E element that has an att attribute, regardless of its value.
Attribute E[att=val] Matches any E element whose att attribute value is exactly equal to val.
Attribute E[att~=val] Matches any E element whose att attribute value is a list of space-separated values, one of which is exactly equal to val.
Attribute E[att|=val] Matches any E element whose att attribute has a hyphen-separated list of values beginning with val.
The :first-child pseudo-class E:first-child Matches element E when E is the first child of its parent.
The link pseudo-classes E:link
E:visited
Matches not yet visited (:link) or already visited (:visited) links.
The dynamic pseudo-classes E:active
E:hover
E:focus
Matches E during certain user actions.
The :language pseudo-class E:lang(c) Matches elements of type E that are in language c.
The :first-line pseudo-element E:first-line Matches the contents of the first formatted line of element E.
The :first-letter pseudo-element E:first-letter Matches the first letter of element E.
The :before and :after pseudo-elements E:before
E:after
Used to insert generated content before or after an element’s content.

I’ll explain each of these selector types in more detail in this two part article, so keep reading. A few terms used in that table and in the rest of this article may need some clarification:

descendant
An element that is the child, grandchild or later descendant of an element in the document tree.
ancestor
An element that is the parent, grandparent or earlier ancestor of an element in the document tree.
child
The direct descendant of an element. No other elements may come between the two in the document tree.
parent
The direct ancestor of an element. No other element may come between the two in the document tree.
sibling
An element that has the same parent as the current element.

Simple and combined selectors

There are two basic categories of selectors: simple and combined.

A simple selector consists of either a type selector or the universal selector followed by zero or more attribute selectors, ID selectors, or pseudo-classes. The following rule contains an example of a simple selector:

  1. p.info { background:#ff0; }

A combined selector (sometimes called a contextual selector) consists of two or more simple selectors separated by a combinator. This is an example of a very simple combined selector:

  1. div p { font-weight:bold; }

The above rule will apply to all p elements that are descendants of a div element.

One pseudo-element may be appended to a selector. In a combined selector, a pseudo-element may only be appended to the last simple selector.

Details on combined selectors, combinators, and pseduo-elements can be found in Part 2 and Part 3 in this series.

The universal selector

The universal selector is represented by an asterisk, “*”, and matches all elements in the document. It’s pretty rare to see it in a style sheet, but the universal selector is actually often used with class and ID selectors. If the universal selector is not the only component of a simple selector, the “*” may be omitted:

  • .myclass is equivalent to *.myclass
  • #myid is equivalent to *#myid

One use of the universal selector that has become quite popular is using it to set the margins and paddings of all elements to zero:

  1. * { margin:0; padding:0; }

This is sometimes referred to as the Global White Space Reset.

Type selectors

A type selector matches every instance of a particular element type. The following rule matches all paragraph elements in the document and sets their font size to 2em:

  1. p { font-size:2em; }

The class selector

The class selector is represented by a full-stop, “.”, and targets elements based on the value of their class attribute. The following rule will apply to all p elements with a class name of “info”:

  1. p.info { background:#ff0; }

You can assign multiple class names to an element – the class attribute can hold a space separated list of class names. Class selectors can then be used to target only elements which have several class names. This rule will match p elements which have both “info” and “error” in their list of class names:

  1. p.info.error { color:#900; font-weight:bold; }

Note: Multiple class selectors do not work in current versions of Internet Explorer, but will be supported in IE7.

The element type does not have to be specified. Leaving it out is the same as using a universal selector instead of a type selector. This rule will match all elements with a class name of “info”, regardless of their type:

  1. .info { background:#ff0; }

The ID selector

The ID selector is represented by a hash sign, “#”, and targets elements based on their id value. This rule will apply to an element whose id is “info”, regardless of which element type it is:

  1. #info { background:#ff0; }

If you also specify an element type, the rule will only apply to elements of that type:

  1. p#info { background:#ff0; }

It is important to remember that ID selectors have higher specificity than class selectors, and that an id value must be unique within a document. Therefore an ID selector can only apply to a single element in a document.

To be continued…

Ok, that’s it for Part 1 of this article series. In Part 2 I will walk you through combinators, combined selectors, grouping, and attribute selectors, and in Part 3 I will take a closer look at pseudo-classes and pseudo-elements.

Translations

This article has been translated into the following languages:

Posted on September 26, 2005 in CSS

Comments

  1. Good stuff. Will you be covering the merits of different selector choices? For example when it might be beneficial to use p.class { … } or p[class=”class”] { … } to accomplish styling tasks. And which type of selector will win out in a situation such as that.

    I’ve been meaning to write up about approaches to selectors for a while.

  2. Thanks for this timely post!

    I’m beginning work on a new site design, and though I feel pretty comfortable working in CSS already, I haven’t had the patience to become familiar with all the selectors. Ideas are already spinning in my head. Can’t wait for parts 2 and 3.

  3. Thanks for starting this, Roger. Will you be pointing out which selectors IE6 does not support?

  4. Great Start. Can you also specify which of these are supported by IE6 ?

  5. Great article Roger! Now, we just have to wait for, like, 3 years before every web browser support those selectors ;-)

  6. Excellent post, have learned something new already. Looking forward to parts two and three! Cheers.

  7. Child, adjacent, attribute, :active, :focus, :hover, :lang(c), :before and :after are not or severely broken supported by IE.

    All the other selectors are usable in IE, to some extend.

  8. September 26, 2005 by Roger Johansson (Author comment)

    Matt: I haven’t planned on covering the merits of different selector choices. That subject is probably worth an article of its own.

    Kim, Manu: Yes, I’m going to cover what does not work in IE up to version 6.

  9. Great article, both for learning and as a reference. Keep ‘em coming =)

  10. It should be noted that this does not work in IE

    p.info.error { color:#900; font-weight:bold; }

    Nor does this:

    p.info#error { color:#900; font-weight:bold; }

  11. …an id value must be unique within a document. Therefore an ID selector can only apply to a single element in a document.

    While that is generally true (since any id in a document is supposed to be unique), in the case of an erroneous document that contains 2 or more elements with the same ID, the id selector will select all of them.

  12. Matt: I haven’t planned on covering the merits of different selector choices. That subject is probably worth an article of its own.

    I think that could be beneficial to people and has the potential to be interesting. Will you be willing do add it to the list?

  13. Do we need yet another CSS recap? Yes we do! Thanks for the cheat sheet ;-)

    I’d like to add that Opera (my browser of choice) still doesn’t honour :lang() pseudo selectors when the language is specified with xml:lang (as it should be for XHTML documents and MUST be for XHTML 1.1 documents).

    So you can do:

    a[hreflang=’de’]:after {content:”\A0(in German)”;}

    but not:

    :lang(fr) a[hreflang=’de’]:after {content:”\A0(en allemand)”;}

    which does work in Firefox both with lang and xml:lang.

    Perhaps you’ll talk about namespaces in CSS some time?

  14. [Partially related] As for the lack of css ‘type’ support (for IE) I’ve put together this little JavaScript to make up for styling input’s by type: appendInputTypeClasses.js will append a class attribute of which kind of type attribute the input contains.

  15. September 28, 2005 by Markus

    I’ll have to say, even more thorough than I expected. Great!

  16. Nice article,

    I wasn’t aware of the * {margin: 0; padding: 0;} rule - will have to try that one to set entire document properties. My question is though, does IE support this feature, yet?

    Look forward to the next couple of articles - keep up the good work,

  17. September 29, 2005 by Roger Johansson (Author comment)

    Chris: Ah, I forgot to mention that. I added a note about it.

    Lachlan:

    in the case of an erroneous document that contains 2 or more elements with the same ID, the id selector will select all of them

    Is that true for all user agents?

    Adam: Added that to my to-do list :-)

    Dustin: That looks useful. Thanks!

    Kai: Yep, the universal selector works in IE and pretty much every other browser currently in use.

  18. October 2, 2005 by oonoo

    great article! can’t wait for part 2.

  19. What Lachlan said is correct. It is not clearly said in the specification but each element with a certain identifier should be matched when that identifier is used in the style sheet. (Difference between author and user agent requirements.)

  20. very great article…..I’m going to read the part 2 :)

  21. January 14, 2006 by Telewizory

    Great article, both for learning and as a reference. Keep ‘em coming =).

  22. January 28, 2006 by Alexander Sandström

    Pseudo-element selectors should be preceded by two colons (::), to to ease the discimination between pseudo-classes and pseudo-elements.

    Eg. p::first-line { color:thistle; }

    Since alot of people will use this article to learn css selectors (I did), it would be great if this error could be corrected.

    More info: http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#pseudo-elements (see the first three paragraphs)

  23. January 29, 2006 by Roger Johansson (Author comment)

    Alexander: That syntax is new for CSS 3, which is currently a working draft. This article is about CSS 2.1 selectors, which do not use the :: notation. So it is not an error, just a difference in notation between different versions of CSS.

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.