JavaScript Event composedPath() Method

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Baseline Widely available
Instance method

What You’ll Learn

The composedPath() method returns an array of EventTarget objects on which listeners will be invoked—the event’s path. Learn how it pairs with composed, why open vs closed shadow roots differ, and how to map the path for debugging—with five examples and try-it labs.

01

Kind

Instance method

02

Returns

EventTarget[]

03

Means

Listener path

04

Params

None

05

Pairs with

composed

06

Status

Baseline widely

Introduction

When you click a nested button, the event does not only touch that button. It travels a path: the target, then parents, then document, then window (depending on the event).

event.composedPath() returns that path as an array. With Shadow DOM, the path can also include shadow nodes—unless the shadow root is closed, which hides internals from the path you see outside (as MDN demonstrates).

💡
Beginner tip

Call composedPath() inside a listener while the event is being dispatched. Map nodes with node.nodeName (or String(node) for Window) to print a readable chain.

Understanding Event.composedPath()

An instance method that returns the event’s path: an array of objects on which listeners will be invoked.

  • Return valueEventTarget[] along the dispatch path.
  • No parameters — call event.composedPath().
  • Shadow DOM — may include shadow nodes when the tree is open / visible on the path.
  • Closed roots — nodes inside a closed shadow tree are not included (path stops at the host from the outside).
  • Baseline Widely available on MDN (since January 2020); also in Web Workers.

📝 Syntax

JavaScript
composedPath()

Parameters

None.

Return value

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

Typical pattern

JavaScript
document.addEventListener("click", (event) => {
  const labels = event.composedPath().map((node) =>
    node.nodeName || String(node)
  );
  console.log(labels.join(" → "));
});

⚡ Quick Reference

GoalCode / note
Get pathevent.composedPath()
Readable labelspath.map(n => n.nodeName || String(n))
Contains element?path.includes(myEl)
Deepest targetOften path[0] (also see event.target)
MDN statusBaseline Widely available (since January 2020)

🔍 At a Glance

Four facts to remember about composedPath().

Returns
array

EventTargets

Args
none

No params

Shadow
open/closed

Path may hide

Baseline
widely

Since Jan 2020

Examples Gallery

Examples follow MDN Event: composedPath(). Use View Output or Try It Yourself.

📚 Getting Started

Print the path for a nested click and compare with target.

Example 1 — Log a Readable Path

Click nested elements and join nodeName labels.

JavaScript
document.addEventListener("click", (event) => {
  const path = event.composedPath().map((n) =>
    n.nodeName || String(n)
  );
  console.log(path.join(" → "));
});
Try It Yourself

How It Works

The array starts at the deepest target and walks outward toward the window.

Example 2 — path[0] vs event.target

Confirm the first path entry matches the event target.

JavaScript
button.addEventListener("click", (event) => {
  const path = event.composedPath();
  console.log(path[0] === event.target); // usually true
  console.log(event.target.nodeName);
});
Try It Yourself

How It Works

Use target for the origin; use the full path when you need ancestors too.

📈 Path Checks & Shadow DOM

Test membership, then compare open vs closed shadow roots (MDN).

Example 3 — Did the Click Happen Inside a Panel?

Use path.includes(panel) instead of walking parents yourself.

JavaScript
document.addEventListener("click", (event) => {
  const inside = event.composedPath().includes(panel);
  out.textContent = inside
    ? "Click was inside the panel"
    : "Click was outside the panel";
});
Try It Yourself

How It Works

This is handy for “click outside to close” menus when you already have the path.

Example 4 — Open Shadow Path (MDN Idea)

With mode: "open", the path can include the inner p and ShadowRoot.

JavaScript
// Custom element attaches open shadow + 

document.documentElement.addEventListener("click", (e) => { console.log(e.composed); // true for click console.log(e.composedPath().map((n) => n.nodeName || String(n))); // May include: P, #document-fragment, OPEN-SHADOW, BODY, … });

Try It Yourself

How It Works

Open mode lets outside code see into the shadow path for composed events like click.

Example 5 — Closed Shadow Path (MDN Idea)

With mode: "closed", the path stops at the host—no inner p.

JavaScript
// Same click listener; closed-shadow hides internals:
// composedPath may look like:
// CLOSED-SHADOW → BODY → HTML → Document → Window
// (no P / ShadowRoot entries from outside)
Try It Yourself

How It Works

Encapsulation: listeners still run for composed UI events, but the path does not expose closed internals.

🚀 Common Use Cases

  • Debugging where an event travels in nested UI.
  • Web components: understand open vs closed shadow paths.
  • “Click outside” detection via path.includes(panel).
  • Teaching capture / bubble alongside a concrete path array.
  • Comparing with event.composed when designing custom events.

🔧 How It Works

1

Event is dispatched

Browser builds the path of targets for this event.

Dispatch
2

Shadow rules apply

Open trees may appear on the path; closed trees hide internals.

Shadow
3

You call composedPath()

Receive the array of EventTargets for this event.

Call
4

Inspect or filter

Map labels, check includes, or compare with composed.

📝 Notes

  • MDN: Baseline Widely available (since January 2020) — no Deprecated / Experimental / Non-standard banner.
  • Available in Web Workers.
  • Takes no parameters; returns an array of EventTargets.
  • Closed shadow roots omit inner nodes from the path seen outside.
  • Related learning: composed, target, currentTarget, type, JavaScript hub.

Universal Browser Support

Event.composedPath() is marked Baseline Widely available on MDN (since January 2020). Logos use the shared browser-image-sprite.png sprite from this project. It is also available in Web Workers.

Baseline · Widely available

Event.composedPath()

Returns the event path as an array of EventTarget objects (shadow nodes may be omitted for closed roots).

Universal Widely available
Google Chrome Full support · Desktop & Mobile
Full support
Mozilla Firefox Full support · Desktop & Mobile
Full support
Apple Safari Full support · macOS & iOS
Full support
Microsoft Edge Full support · Chromium
Full support
Opera Full support · Modern versions
Full support
Internet Explorer Not supported (use modern browsers)
Unavailable
Event.composedPath() Excellent

Bottom line: Use composedPath() to see the full listener path—especially with Shadow DOM—and pair it with Event.composed.

Conclusion

Event.composedPath() returns the array of targets on the event’s path. Use it to debug flow, check ancestors, and understand how open vs closed shadow trees change what you can see.

Continue with initEvent(), composed, target, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Call it inside an active event handler
  • Map to nodeName for readable logs
  • Pair with event.composed for shadow design
  • Use includes for ancestor checks
  • Prefer event.target when you only need the origin

❌ Don’t

  • Expect closed shadow internals in the outer path
  • Confuse the path array with currentTarget alone
  • Assume every synthetic event is composed
  • Mutate the returned array as if it owned the live tree
  • Skip testing open vs closed when shipping components

Key Takeaways

Knowledge Unlocked

Five things to remember about composedPath()

The event’s path as an EventTarget array.

5
Core concepts
🎯02

path[0]

~ event.target

Origin
🎨03

composed

boundary flag

Pair
🔒04

Closed

hides internals

Shadow
🎯05

Baseline

since Jan 2020

Status

❓ Frequently Asked Questions

It returns an array of EventTarget objects on which listeners will be invoked for that event—the path the event travels through the DOM (and shadow trees when allowed).
No. MDN marks Event.composedPath() as Baseline Widely available (since January 2020). It is not Deprecated, Experimental, or Non-standard. It is also available in Web Workers.
composed says whether the event can cross a shadow boundary. composedPath() shows the actual objects on the path. For closed shadow roots, inner nodes may be omitted from the path you see outside.
Often yes for a normal click: the first entry is the deepest target. Prefer event.target for the origin, and composedPath() when you need the full chain.
If a shadow root was created with mode: "closed", composedPath() does not include nodes inside that closed tree when observed from outside—only as far as the host element.
Debugging event flow, web components, checking whether a click happened inside a specific ancestor (path.includes(el)), or comparing open vs closed shadow encapsulation.
Did you know?

For a composed click, event.composed is true for both open and closed shadow hosts—but composedPath() still differs. The boolean answers “can it cross?”; the method answers “what can I see on the path?”

Next: initEvent()

Learn the deprecated initializer and migrate to Event().

initEvent() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful