What CSS3 selectors does jQuery really support, e.g. :nth-last-child()?

While jQuery advertises compliance with the Selectors level 3 standard on its home page, it does not fully implement the spec. In its own Selectors documentation, it clarifies that it “[borrows] from CSS 1–3, and then [adds] its own” selectors.1

Starting from jQuery 1.9, virtually all selectors in the level 3 standard are supported by Sizzle (its underlying selector library), with the following exceptions:

The following level 3 selectors are implemented in jQuery 1.9 and newer, but not jQuery 1.8 or older2:

Additionally:

  • :lang(), introduced in CSS2, is also missing.

The reason why your selector appears to work in Firefox, Chrome and IE9 is because jQuery first passes the selector string to the native document.querySelectorAll() implementation before falling back to Sizzle. Since it is a valid CSS selector, document.querySelectorAll() will successfully return a node list for jQuery to use, thereby obviating the use of Sizzle.

In the event that document.querySelectorAll() fails, jQuery automatically falls back to Sizzle. There are a number of scenarios that can cause it to fail:

  • The selector is invalid, not supported, or otherwise cannot be used (see the Selectors API spec for details).

  • The document.querySelectorAll() method itself is not supported (jQuery actually tests this with a simple if statement so it doesn’t fail in that sense of the word, but you get the picture).

In your case, although IE9 and IE8 implement document.querySelectorAll(), IE8 doesn’t support :nth-last-child(). Since jQuery/Sizzle doesn’t implement :nth-last-child() either, there’s no fallback behavior to use, resulting in complete failure on IE8.

If you’re not able to update jQuery to 1.9 even at the very least (the backward-compatible release branch), you can always use the custom selector extensions to implement the missing pseudo-classes yourself. However, since jQuery 1.9 adds support for the above selectors while maintaining compatibility with old IE versions, it is best to update to that version at the very minimum if you need the compatibility.


1 It does support :contains(), last defined in this old CR revision of the spec before being dropped later, as well as extending :not() from the standard. The differences between jQuery’s implementation and the current standard are covered in this question.

2 A few other selectors (like the + and ~ sibling combinators, :empty, :lang() and some CSS2 attribute selectors) were going to be dropped as well during jQuery’s early development, just because John Resig didn’t think anybody would use them. Almost all of them made it into the final release after some more tests were made available. :lang() was the only one that never made it into any release before 1.9, as stated above.

Leave a Comment