What aged in jQuery · 2 of 8

A selector engine the browser already has

jQuery shipped its own CSS selector engine because browsers couldn't be trusted to have one. Today they all do — and theirs supports :has().

Why it made sense

Before querySelectorAll was universal, jQuery's Sizzle engine was the only portable way to select by CSS, and it added handy extensions like :visible, :first and :eq() along the way.

What changed

jQuery 4.0 inlined Sizzle into its selector module, dropped legacy pseudos and introduced .even() and .odd() to replace :even/:odd. Custom extensions that remain, such as :visible, still aren't CSS, so selectors using them can't be handed to the browser and fall back to JavaScript matching. Code written against those extensions also doesn't transfer to querySelector, CSS or other tools.

What jsKjs does instead

jsKjs passes every selector straight to querySelectorAll. No engine is downloaded, every selector your browser supports works — including :has() and :is() — and an invalid selector throws a clear SyntaxError rather than silently matching nothing. Positional needs are methods: .first(), .eq(2), .filter(fn).

jQuery

JavaScript
$('li:visible:first');          // jQuery-only syntax
$('tr:even').addClass('zebra');

jsKjs

JavaScript
$('li').filter((i, el) => el.offsetParent).first();
$('tr:nth-child(odd)').addClass('zebra');     // real CSS — also works in your stylesheet
$('.card:has(img)').addClass('with-media');   // native :has()

Sources