Sometimes a component needs to know exactly what content was projected into a slot — for example, to count items or apply logic based on slotted children. This lesson covers the slotchange event and assignedNodes().
Detecting When Slotted Content Changes
The slotchange event fires on a <slot> element whenever the set of nodes assigned to it changes — when the consumer adds, removes, or reorders projected children. This is a native platform event (not Lit-specific), and Lit lets you listen to it with the ordinary @slotchange=${handler} binding.
Inside the handler, calling event.target.assignedNodes() (or assignedElements() to skip text nodes) on the slot gives you the actual list of currently projected nodes, which is useful for validation, counting, or reacting to structural changes in the consumer's content.
assignedElements() returns only element nodes (skipping stray whitespace text nodes), giving an accurate count of projected <tab-item> children.
assignedNodes() vs assignedElements()
slotEl.assignedNodes(); // all nodes, including text nodes
slotEl.assignedNodes({ flatten: true }); // resolves through nested slots too
slotEl.assignedElements(); // only element nodes, no text
slotEl.assignedElements({ flatten: true }); // element nodes, resolved through nesting
assignedNodes() includes whitespace-only text nodes between elements, which is rarely what you want for counting.
assignedElements() filters to element nodes only — the more commonly useful method.
{ flatten: true } resolves assignment through any further nested <slot> elements, useful for deeply composed components.
slotchange fires on the <slot> element itself, so bind the listener directly on that <slot>, not on a wrapping element.
slotchange Cheat Sheet
Core facts about the slotchange event.
Fact
Detail
Fires on
The <slot> element itself
Fires when
Assigned nodes are added, removed, or reordered
Does NOT fire when
Content *inside* an already-assigned node changes
Bubbles?
Yes
Composed?
Yes — crosses the shadow boundary
Get current content
event.target.assignedElements()
Validating or Filtering Slotted Content
A component that expects only specific child element types (like a <tab-list> that should only contain <tab-item> elements) can use slotchange to inspect and warn about unexpected children, which helps catch consumer mistakes early during development.
slotchange only fires when the *set* of assigned nodes changes — adding, removing, or reordering direct children. It does not fire if a slotted element's own internal content later changes (e.g. its text is edited via textContent), since that node is still the same assigned node.
Use slotchange for structural changes: children added, removed, or reordered.
Use a MutationObserver on the slotted content itself if you need to react to changes inside those nodes.
Don't rely on slotchange as a general-purpose 'anything changed' signal — it's specifically about slot assignment.
Common Mistakes
Using assignedNodes() and then miscounting because whitespace text nodes are included alongside real elements.
Expecting slotchange to fire when content *inside* an already-slotted element changes, rather than only on assignment changes.
Attaching the @slotchange listener to a wrapping element instead of directly to the <slot> itself.
Forgetting { flatten: true } when a component's slots can themselves contain further nested slotted components.
Key Takeaways
slotchange fires on a <slot> whenever its assigned nodes are added, removed, or reordered.
assignedElements() is usually more useful than assignedNodes() since it filters out stray text nodes.
slotchange does not fire for changes happening *inside* an already-assigned node — only for assignment changes themselves.
This is a native platform event, usable with the same @slotchange=${handler} binding as any other event.
Pro Tip
Reach for slotchange specifically when a component's own logic (not just its styling) depends on what was projected — for purely visual layout differences based on slot content, CSS :has() or ::slotted() selectors are often simpler than JavaScript.
You now understand the slotchange event. Next, look at broader patterns for composing components together.