Note that, as the quote in emmanuel's answer states, CSS2.1 has slight terminology differences from the current level 3 standard, so I would consider the CSS2.1 definitions obsolete. The syntax remains pretty much the same, but the terminology is more definite: a simple selector now always refers to any one component in each of what are now known as simple selector sequences, or better yet, compound selectors.
Here is the same quote from the level 3 standard, with just the relevant bits:
4. Selector syntax
A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
Unlike CSS2.1, this spec does not use the phrase "in any order" explicitly, but it's easily implied by the fact that it only states the exception for type/universal selectors. As far as I know the only reason for this exception is that a type selector doesn't have any special symbol, which makes it impossible to distinguish from another simple selector were it to occur anywhere else in a compound selector. A universal selector, despite being represented by an asterisk, really just means "any type of element" — a wildcard type selector, if you will, so it follows the same rule for type selectors.
Also check out the upcoming standard which sees more significant changes (and defines the term "compound selector").
I have a few notes to add:
It is probably widely known by now that the native selector engines used by most browsers evaluate selectors in right-to-left order. There is a misconception that this applies down to the simple selector level; it does not. Not strictly, anyway. There are various optimizations accounting for some common cases, such as the presence of ID selectors, the presence of class selectors, the presence of dynamic pseudo-classes, and so on. These optimizations almost always take place regardless of their position in a compound selector. Nobody in their right mind would look at the rightmost simple selector first, when it's really the type or ID selector that matters most, especially when you consider that most authors place the ID somewhere near the start, and the type selector can only appear at the beginning.
I go into much further detail, with examples, in my answer to this question on the subject of simple selector ordering with regards to selector engines.
It is implied that jQuery's selector engine Sizzle follows the same rules, but keep in mind that, like the ones built into layout engines, this is but one implementation of the standard. The entire nature of implementations is that everyone does some things similarly and others quite differently, so performance cannot be qualified on an extremely granular level.
However, it's pretty much common sense that the fewer simple selectors in a sequence, the less work the selector engine has to do in evaluating the selector. You should only be as specific as you need, and no more than that. For example, you can restrict the context of an ID selector with a class selector or a pseudo-class, but you almost never need to go beyond that.
It's also well known that jQuery optimizes lone ID selectors, class selectors and type selectors to document.getElementById()
, document.getElementsByClassName()
and document.getElementsByTagName()
respectively. You can qualify them with any other selectors and it will still work, but you lose these optimization paths as a trade-off. Similar optimizations exist in native selector engines, but that is as far as similarities go, ones that matter to authors anyway.
Speaking of jQuery, because your question is tagged both jquery-selectors css-selectors, note that jQuery does not support certain dynamic pseudo-classes such as :hover
. The basic principle remains the same, though. (As mentioned in a comment, it can detect elements that are currently :hover
at the time it is called if passed to document.querySelectorAll()
, but for obvious reasons, this is almost never useful.)
So, in short: don't worry about performance when it comes to ordering simple selectors. Any deviations in performance are usually inconsequential, with only the most obvious of exceptions. The syntax doesn't impose any other restrictions except the one that's mentioned above. All you have to do is avoid overqualification, and be consistent.
For example, here is how I order my simple selectors — the syntax allows me to choose any order I like, and this is just what feels right for me:
a#id[attr=val].class1.class2:nth-child(n):link:hover