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>

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


Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Update: Now supported in most major browsers


Note that this can match selectors, not just classes

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;

Method 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.

Method 3

Use element.closest()

See this example DOM:

  <div id="div-01">Here is div-01
    <div id="div-02">Here is div-02
      <div id="div-03">Here is div-03</div>

This is how you would use element.closest:

var el = document.getElementById('div-03');

var r1 = el.closest("#div-02");  
// returns the element with the id=div-02

var r2 = el.closest("div div");  
// returns the closest ancestor which is a div in div, here is div-03 itself

var r3 = el.closest("article > div");  
// returns the closest ancestor which is a div and has a parent article, here is div-01

var r4 = el.closest(":not(div)");
// returns the closest ancestor which is not a div, here is the outmost article

Method 4

Based on the the8472 answer and here is cross-platform 2017 solution:

if (!Element.prototype.matches) {
    Element.prototype.matches =
        Element.prototype.matchesSelector ||
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector ||
        Element.prototype.oMatchesSelector ||
        Element.prototype.webkitMatchesSelector ||
        function(s) {
            var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
            while (--i >= 0 && matches.item(i) !== this) {}
            return i > -1;

function findAncestor(el, sel) {
    if (typeof el.closest === 'function') {
        return el.closest(sel) || null;
    while (el) {
        if (el.matches(sel)) {
            return el;
        el = el.parentElement;
    return null;

Method 5

@rvighne solution works well, but as identified in the comments ParentElement and ClassList both have compatibility issues. To make it more compatible, I have used:

function findAncestor (el, cls) {
    while ((el = el.parentNode) && el.className.indexOf(cls) < 0);
    return el;
  • parentNode property instead of the parentElement property
  • indexOf method on the className property instead of the contains method on the classList property.

Of course, indexOf is simply looking for the presence of that string, it does not care if it is the whole string or not. So if you had another element with class ‘ancestor-type’ it would still return as having found ‘ancestor’, if this is a problem for you, perhaps you can use regexp to find an exact match.

Method 6

This solution should work for IE9 and up.

It’s like jQuery’s parents() method when you need to get a parent container which might be up a few levels from the given element, like finding the containing <form> of a clicked <button>. Looks through the parents until the matching selector is found, or until it reaches the <body>. Returns either the matching element or the <body>.

function parents(el, selector){
    var parent_container = el;
    do {
        parent_container = parent_container.parentNode;
    while( !parent_container.matches(selector) && parent_container !== document.body );

    return parent_container;

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Notify of

Inline Feedbacks
View all comments
Would love your thoughts, please comment.x