jQuery :has() Selector — Match Parents With Descendants
Beginner
7 min read
Updated: Oct 2026
5 examples
Live preview
Definition
What Is the :has() Selector?
:has(selector) (since jQuery 1.1.4) selects elements that contain at least one descendant matching selector — at any nesting depth, not only direct children.
Remember
$("div:has(p)"); // divs with a <p> inside
$("li:has(ul)"); // list items with a nested list
$("article:has(.error)"); // articles that hold an error
// Preferred today:
$("div").has("p"); // same idea, faster path
:has() has been part of jQuery since 1.1.4. It works wherever jQuery runs, but as a jQuery extension it skips the native querySelectorAll fast path — prefer .has() in new code.
✓ jQuery 1.1.4+
jQuery :has()
Supported across jQuery 1.x–3.x where the library is loaded. For modern apps, use $("sel").has("inner") instead of embedding :has() in the selector string.
StableStatus
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
:has()Since 1.1.4
Bottom line: Safe to use for learning and legacy code. Prefer .has() for performance on modern browsers.
Analysis
Performance Notes
Approach
Cost
Best for
$("css").has("sel")
Best
Modern browsers — official recommendation
$("el:has(sel)")
Slower
Short demos / legacy tutorials
Huge DOM + deep trees
Can add up
Narrow the base set first
Because :has() is a jQuery extension, the full query cannot ride native querySelectorAll. Select with CSS, then filter with .has().
Remember
Key Takeaways
Role: keep parents that contain a matching descendant — since 1.1.4.
Prefer:$("el").has("sel") over $("el:has(sel)").
Depth: any descendant counts — not only direct children.
Not text: for words use :contains(); for inner nodes use :has() / .has().
One line::has(sel) keeps elements that contain sel — prefer .has(sel) in modern jQuery.
Frequently Asked Questions
:has(selector) selects elements that contain at least one descendant matching the inner selector. $("div:has(p)") matches every div with a p anywhere inside — not only as a direct child. Available since jQuery 1.1.4.
No. Official docs: the match can exist anywhere among descendants — grandchildren and deeper count. Use the child combinator (>) when you need direct children only.
Official jQuery docs recommend $("div").has("p") instead of $("div:has(p)") for better performance in modern browsers. Separate a pure CSS base selector from the descendant filter.
They look similar. jQuery :has() is a jQuery extension since 1.1.4 and does not use native querySelectorAll the same way. Modern CSS also defines :has(), but in jQuery code prefer .has() on a CSS-selected collection.
:has() filters by descendant elements matching a selector — structure. :contains() filters by visible text substring — content. div:has(p) looks for a p tag; div:contains("Hello") looks for text.
.find() returns the matching descendants. :has() / .has() return the container elements that hold those descendants. $("div").find("p") gives paragraphs; $("div").has("p") gives the divs.