What is event delegation and how does event bubbling work?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Events bubble from the target element up through its ancestors. Delegation attaches one listener to a stable parent and inspects event.target for each bubbled event — fewer listeners, and it keeps working for dynamically added children.
Detailed explanation
When an event fires, it travels in three phases: capturing from the document down to the target, the target phase itself, then bubbling back up through every ancestor. Listeners on parents receive events from their descendants during bubbling (unless stopPropagation cuts it off). Delegation exploits this: instead of wiring a listener onto 200 list items — or re-wiring whenever items are added or removed — you attach one listener to the container, read event.target (and often closest(selector) to find the meaningful ancestor), and act accordingly. Benefits: less memory, simpler cleanup, automatic support for future elements. Use cases include list actions, form validation, and dropdown menus. The inverse is event.stopPropagation(), which halts bubbling when a child must handle something alone.
Example
document.querySelector('#todo-list').addEventListener('click', (e) => {
const item = e.target.closest('li');
if (!item) return;
if (e.target.matches('.delete-btn')) {
item.remove();
} else {
item.classList.toggle('done');
}
});
// Works for every li — including ones added laterInterview tip
Explain the three phases briefly, then show closest() in code. Mentioning 'works for dynamically added elements' demonstrates you know why teams use it in practice.
Common mistakes
- Forgetting closest() and matching event.target too literally, breaking nested markup.
- Confusing bubbling direction — it goes upward from target.