Skip to content

Slotchange and Assigned Nodes

The slotchange event fires on a <slot> element whenever the set of assigned nodes changes. This includes the moment the element first connects to the DOM with children already present, when a child is added or removed from the host element, and when a child’s slot attribute changes.

Listen for it directly on the slot element:

const slot = shadow.querySelector('slot');
slot.addEventListener('slotchange', () => {
console.log('Assigned nodes changed');
});

slot.assignedNodes() returns all nodes currently projected into that slot, including text nodes and comment nodes. slot.assignedElements() returns only Element nodes, which is usually what you want when iterating over projected children.

Both methods accept an options object with a flatten property. Passing { flatten: true } recursively expands any nested slot elements to include their own assigned nodes, which is useful when you have slots inside slots.

class MyList extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = '<slot></slot>';
const slot = shadow.querySelector('slot');
slot.addEventListener('slotchange', () => {
const nodes = slot.assignedElements();
console.log('Slot has', nodes.length, 'elements');
});
}
}
customElements.define('my-list', MyList);

Reacting to slotchange lets your component stay in sync with its projected children without polling or mutation observers. Common patterns include:

  • Counting projected items and reflecting that count in the shadow DOM or as an attribute
  • Validating that only expected element types are slotted in
  • Synchronising aria-label or other accessibility attributes when the number of items changes
  • Wiring up event listeners to newly projected children

The key insight is that your component does not own the light DOM children — the consumer does. The slotchange event is the bridge that lets you react to those external changes.

When does the slotchange event fire on a slot element?
What does slot.assignedElements() return compared to slot.assignedNodes()?
What does { flatten: true } do when passed to assignedNodes()?