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

1

12

According to http://api.jquery.com/category/selectors/ we can use a large amount of CSS selectors in jQuery, but e.g. :nth-last-child() is not mentioned there. However, when I test the following (with jQuery 1.7.1 as from Google), it actually works on Firefox, Chrome, and IE 9, but not on IE 9 in IE 8 emulation mode:

$('li:nth-last-child(2)').css('color', 'red');

So what’s happening? It looks as if jQuery generated CSS code, like li:nth-last-child(2) { color: red } and somehow injected it, which then works OK on browsers that support the selector used. But that would be odd.

Most importantly, is there some trick to make jQuery support such selectors on all browsers?

Chinookan answered 31/7, 2012 at 16:57 Comment(0)
I
37

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.

Incardination answered 31/7, 2012 at 17:5 Comment(4)
Of course, it should be mentioned that jQuery selectors can be extended using: $.expr[':']['nth-last-child'] = function () {...};Courland
@zzzzBov: Thanks for the reminder! I've mentioned that in an edit, and right now I'm trying to come up with my own implementation...Incardination
@Incardination where does it says in api.jquery.com/nth-of-type-selector that it "[borrows] from CSS 1–3, and then [adds] its own" selectors.Cherriecherrita
@Royi Namir: I already have the link in my answer pointing to where it says that. And it looks like jQuery 1.9 added support for other selectors, so I will have to update this answer later.Incardination

© 2022 - 2024 — McMap. All rights reserved.