Find the closest ancestor element that has a specific class

How can I find an element's ancestor that is closest up the tree that has a particular class, in pure JavaScript? For example, in a tree like so:

<div class="far ancestor">
    <div class="near ancestor">
        <p>Where am I?</p>
    </div>
</div>

Then I want div.near.ancestor if I try this on the p and search for ancestor.


Solution 1:

Update: Now supported in most major browsers

document.querySelector("p").closest(".near.ancestor")

Note that this can match selectors, not just classes

https://developer.mozilla.org/en-US/docs/Web/API/Element.closest


For legacy browsers that do not support closest() but have matches() one can build selector-matching similar to @rvighne's class matching:

function findAncestor (el, sel) {
    while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el,sel)));
    return el;
}

Solution 2:

This does the trick:

function findAncestor (el, cls) {
    while ((el = el.parentElement) && !el.classList.contains(cls));
    return el;
}

The while loop waits until el has the desired class, and it sets el to el's parent every iteration so in the end, you have the ancestor with that class or null.

Here's a fiddle, if anyone wants to improve it. It won't work on old browsers (i.e. IE); see this compatibility table for classList. parentElement is used here because parentNode would involve more work to make sure that the node is an element.