Find Closest Common Ancestor in jQuery
While jQuery does not provide a single built-in method specifically
named for finding the common ancestor of two elements, you can easily
achieve this by combining native traversal methods. This article covers
the most efficient and readable jQuery patterns—primarily utilizing
.parents(), .has(), and
.closest()—to determine the lowest common ancestor of any
two DOM elements.
The Most Reliable
Method: .parents().has().first()
The most idiomatic and robust way to find the closest common ancestor in jQuery is:
const $commonAncestor = $(elementA).parents().has(elementB).first();How It Works:
$(elementA).parents(): Retrieves all ancestor elements ofelementA, ordered from the direct parent upwards to the<html>root..has(elementB): Filters that list of ancestors to only include elements that containelementBas a descendant..first(): Selects the first matching element in the collection, which represents the nearest (deepest) ancestor shared by both nodes.
Alternative
Method: .closest() with Ancestor Collections
Another concise technique passes the ancestor collection of the
second element directly into .closest():
const $commonAncestor = $(elementA).closest($(elementB).parents());How It Works:
$(elementB).parents(): Gathers all ancestors ofelementB..closest(...): Traverses up the DOM tree starting fromelementAuntil it finds an element that matches any node in the provided collection.
Note: Because .closest() begins its check with
elementA itself, this method will return
elementA if elementA happens to be an ancestor
of elementB.
Handling Edge Cases (Ancestor-Descendant Relationships)
If one element might directly contain the other, standard traversal must account for whether the parent element itself counts as an ancestor.
If either element can be its own common ancestor:
function getClosestCommonAncestor(a, b) {
const $a = $(a);
const $b = $(b);
// If identical
if ($a.is($b)) return $a;
// Check if one contains the other, otherwise find shared parent
if ($a.has($b).length) return $a;
if ($b.has($a).length) return $b;
return $a.parents().has($b).first();
}Creating a Reusable jQuery Plugin
You can extend jQuery's prototype to make this function accessible across your codebase:
jQuery.fn.commonAncestor = function(target) {
return this.parents().has(target).first();
};
// Usage:
const $ancestor = $('#item-one').commonAncestor('#item-two');