The composed property is a read-only boolean on every Event: true if the event can cross the shadow DOM boundary into the light DOM, false if the shadow root is the last stop. Learn how it pairs with bubbles, how to set it on synthetic events, and how composedPath() reveals the path—with five examples and try-it labs.
01
Kind
Instance property
02
Type
boolean (read-only)
03
Means
Cross shadow boundary?
04
Set via
Constructor options
05
Path
composedPath()
06
Status
Baseline widely
Fundamentals
Introduction
Web Components hide markup inside a shadow tree. Some events that start inside that tree should still reach listeners on the page outside—others should stay private. event.composed is the flag that answers that question.
Browser UI events such as click are composed, so a click inside a custom element can still be heard on document. Most custom synthetic events are not composed unless you pass { composed: true } to new Event().
💡
Beginner tip
MDN: crossing the shadow boundary for bubbling still needs bubbles: true as well. Think of composed as “allowed to leave the shadow tree” and bubbles as “travels up ancestors.”
Concept
Understanding Event.composed
An instance property that answers: “After this event reaches the shadow root, may it continue into the standard DOM?”
Value — true if it can cross; false if the shadow root is the last node.
Read-only — set only at construction for synthetic events.
body heard notify
(only after the composed:true dispatch)
How It Works
Both dispatches bubble inside the shadow tree; only composed: true continues past the shadow root.
Example 5 — Open vs Closed Shadow (MDN Idea)
Clicks are composed; composedPath() shows different detail for open vs closed.
JavaScript
// After defining and like MDN:
document.querySelector("html").addEventListener("click", (e) => {
console.log(e.composed); // true for click
console.log(e.composedPath());
// Open: may include inner
, ShadowRoot, host, ...
// Closed: often starts at the host, without inner nodes
});
Event.composed 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.composed
Read-only boolean: true if the event can cross the shadow DOM boundary into the standard DOM.
UniversalWidely available
Google ChromeFull support · Desktop & Mobile
Full support
Mozilla FirefoxFull support · Desktop & Mobile
Full support
Apple SafariFull support · macOS & iOS
Full support
Microsoft EdgeFull support · Chromium
Full support
OperaFull support · Modern versions
Full support
Internet ExplorerNot supported
Unavailable
Event.composedExcellent
Bottom line: Use composed for shadow-aware event design. Pair with bubbles for bubble-phase escape, and inspect paths with composedPath().
Wrap Up
Conclusion
Event.composed tells you whether an event may leave a shadow tree for the light DOM. Browser UI events usually can; your synthetic events only can if you set { composed: true }.
Pass { bubbles: true, composed: true } for public component events
Keep internal signals non-composed by default
Use composedPath() when debugging shadow events
Remember UI events like click are already composed
Document which custom events are meant to escape the shadow tree
❌ Don’t
Assign event.composed = true after creation
Expect non-composed events to reach document from shadow
Forget bubbles when you need bubble-phase escape
Assume closed shadow paths include private inner nodes
Confuse composed with cancelable
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about composed
Shadow-boundary flag for Web Component events.
5
Core concepts
🎨01
Boolean
read-only
API
🔁02
true
can leave shadow
Meaning
📝03
Set once
constructor options
Create
📈04
composedPath
see the route
Debug
🎯05
Baseline
since Jan 2020
Status
❓ Frequently Asked Questions
It is a read-only boolean on an Event. It is true if the event can cross the shadow DOM boundary into the standard DOM after reaching the shadow root, and false if the shadow root is the last node offered the event.
No. MDN marks Event.composed as Baseline Widely available (since January 2020). It is not Deprecated, Experimental, or Non-standard. It is also available in Web Workers.
No. Browser-dispatched UI events (click, touch, mouseover, copy, paste, and similar) are composed. Most other event types are not, including synthetic events created without { composed: true }.
Propagation across the boundary still needs bubbling when you rely on the bubble phase. MDN notes propagation only occurs if bubbles is also true. composedPath() shows the path the event follows.
Use new Event("my-event", { bubbles: true, composed: true }) (and cancelable if needed), then dispatch it from inside the shadow tree when outer listeners must hear it.
event.composedPath() returns an array of objects the event will travel through, including nodes across shadow boundaries when the event is composed. Closed shadow roots may hide inner nodes from the path seen outside.
Did you know?
MDN notes that capturing-only composed events are still handled at the host as if they were in the AT_TARGET phase—another reason shadow hosts feel like special targets for composed UI events.