Element.closest()

You’re reading the English version of this content since no translation exists yet for this locale. Help us translate this article!

Starting with the Element itself, the closest() method traverses parents (heading toward the document root) of the Element until it finds a node that matches the provided selectorString. Will return itself or the matching ancestor. If no such element exists, it returns null.

Syntax

var closestElement = targetElement.closest(selectors);

Parameters

  • selectors is a DOMString containing a selector list such as
    "p:hover, .toto + q".

Result value

  • closestElement is the Element which is the closest ancestor of the selected element. It may be null.

Exceptions

  • SyntaxError is thrown if the selectors is not a valid selector list string.

Example

HTML

<article>
  <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>
    </div>
  </div>
</article>

JavaScript

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 it is the div-03 itself

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

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

Polyfill

For browsers that do not support Element.closest(), but carry support for element.matches() (or a prefixed equivalent, meaning IE9+), a polyfill exists:

if (!Element.prototype.matches) {
  Element.prototype.matches = Element.prototype.msMatchesSelector || 
                              Element.prototype.webkitMatchesSelector;
}

if (!Element.prototype.closest) {
  Element.prototype.closest = function(s) {
    var el = this;

    do {
      if (el.matches(s)) return el;
      el = el.parentElement || el.parentNode;
    } while (el !== null && el.nodeType === 1);
    return null;
  };
}

However, if you really do require IE 8 support, then the following polyfill will do the job very slowly, but eventually. However, it will only support CSS 2.1 selectors in IE 8, and it can cause severe lag spikes in production websites.

if (window.Element && !Element.prototype.closest) {
  Element.prototype.closest =
  function(s) {
    var matches = (this.document || this.ownerDocument).querySelectorAll(s),
        i,
        el = this;
    do {
      i = matches.length;
      while (--i >= 0 && matches.item(i) !== el) {};
    } while ((i < 0) && (el = el.parentElement));
    return el;
  };
}

Specifications

Specification Status Comment
DOM
The definition of 'Element.closest()' in that specification.
Living Standard Initial definition.

Browser compatibility

Update compatibility data on GitHub
DesktopMobile
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung Internet
closestChrome Full support 41Edge Full support 15Firefox Full support 35IE No support NoOpera Full support 28Safari Full support 6WebView Android Full support 41Chrome Android Full support 41Firefox Android Full support 35Opera Android Full support YesSafari iOS Full support 9Samsung Internet Android Full support Yes

Legend

Full support  
Full support
No support  
No support

Compatibility notes

  • In Edge document.createElement(tagName).closest(tagName) will return null if the element is not first attached to the DOM

See also