Event: composedPath() method

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.

Note: This feature is available in Web Workers.

The composedPath() method of the Event interface returns the event's path which is an array of the objects on which listeners will be invoked. This does not include nodes in shadow trees if the shadow root was created with its ShadowRoot.mode closed.

Syntax

js
composedPath()

Parameters

None.

Return value

An array of EventTarget objects representing the objects on which an event listener will be invoked.

Examples

In the following example, which you can try out at https://mdn.github.io/web-components-examples/composed-composed-path/, we define two trivial custom elements, <open-shadow> and <closed-shadow>, both of which take the contents of their text attribute and insert them into the element's shadow DOM as the text content of a <p> element. The only difference between the two is that their shadow roots are attached with their modes set to open and closed respectively.

js
customElements.define(
  "open-shadow",
  class extends HTMLElement {
    constructor() {
      super();

      const pElem = document.createElement("p");
      pElem.textContent = this.getAttribute("text");

      const shadowRoot = this.attachShadow({ mode: "open" });
      shadowRoot.appendChild(pElem);
    }
  },
);

customElements.define(
  "closed-shadow",
  class extends HTMLElement {
    constructor() {
      super();

      const pElem = document.createElement("p");
      pElem.textContent = this.getAttribute("text");

      const shadowRoot = this.attachShadow({ mode: "closed" });
      shadowRoot.appendChild(pElem);
    }
  },
);

We then insert one of each element into our page:

html
<open-shadow text="I have an open shadow root"></open-shadow>
<closed-shadow text="I have a closed shadow root"></closed-shadow>

Then include a click event listener on the <html> element:

js
document.querySelector("html").addEventListener("click", (e) => {
  console.log(e.composed);
  console.log(e.composedPath());
});

When you click on the <open-shadow> element and then the <closed-shadow> element, you'll notice two things. First, the composed property returns true because the click event is always able to propagate across shadow boundaries. Second, you'll notice a difference in the value of composedPath for the two elements. The <open-shadow> element's composed path is this:

Array [ p, ShadowRoot, open-shadow, body, html, HTMLDocument https://mdn.github.io/web-components-examples/composed-composed-path/, Window ]

Whereas the <closed-shadow> element's composed path is a follows:

Array [ closed-shadow, body, html, HTMLDocument https://mdn.github.io/web-components-examples/composed-composed-path/, Window ]

In the second case, the event listeners only propagate as far as the <closed-shadow> element itself, but not to the nodes inside the shadow boundary.

Specifications

Specification
DOM
# ref-for-dom-event-composedpath①

Browser compatibility

desktop mobile server
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Bun
Deno
Node.js
composedPath
Chrome – No support
Chrome 50 – 52 (Release date: 2016-04-13)
altname
altname Alternate name: deepPath
Chrome – Full support
Chrome 53 (Release date: 2016-08-31)
footnote Full support
Edge – Full support
Edge 79 (Release date: 2020-01-15)
footnote Full support
Firefox – Full support
Firefox 59 (Release date: 2018-03-13)
footnote Full support
Opera – No support
Opera 37 – 39 (Release date: 2016-05-04)
altname
altname Alternate name: deepPath
Opera – Full support
Opera 40 (Release date: 2016-09-20)
footnote Full support
Safari – Full support
Safari 10 (Release date: 2016-09-20)
footnote Full support
Chrome Android – No support
Chrome Android 50 – 52 (Release date: 2016-04-13)
altname
altname Alternate name: deepPath
Chrome Android – Full support
Chrome Android 53 (Release date: 2016-09-07)
footnote Full support
Firefox for Android – Full support
Firefox for Android 59 (Release date: 2018-03-13)
footnote Full support
Opera Android – No support
Opera Android 37 – 37 (Release date: 2016-06-16)
altname
altname Alternate name: deepPath
Opera Android – Full support
Opera Android 41 (Release date: 2016-10-25)
footnote Full support
Safari on iOS – Full support
Safari on iOS 10 (Release date: 2016-09-13)
footnote Full support
Samsung Internet – No support
Samsung Internet 5 – 5.4 (Release date: 2016-12-15)
altname
altname Alternate name: deepPath
Samsung Internet – Full support
Samsung Internet 6 (Release date: 2017-08-23)
footnote Full support
WebView Android – No support
WebView Android 50 – 52 (Release date: 2016-04-13)
altname
altname Alternate name: deepPath
WebView Android – Full support
WebView Android 53 (Release date: 2016-09-07)
footnote Full support
WebView on iOS – Full support
WebView on iOS 10 (Release date: 2016-09-13)
footnote Full support
Bun – Full support
Bun 1 (Release date: 2023-09-08)
footnote Full support
Deno – Full support
Deno 1 (Release date: 2020-05-13)
footnote Full support
Node.js – Full support
Node.js 14.5 (Release date: 2020-06-30)
footnote
footnote Returns an array with either the event itself or empty.
footnote This is not used in Node.js and is provided purely for completeness.

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
See implementation notes.
Uses a non-standard name
Has more compatibility info.