Event Bubbling
Introduction
Event bubbling is the phase where an event starts at the target and then travels upward through ancestors. A click on a button can be observed by the button, its card, its list, and higher containers.
This is why one user action can trigger multiple handlers. It is also the foundation for event delegation.
Why This Matters
Bubbling explains common interview snippets: a child click logs before a parent click, stopPropagation changes the order, and a parent can handle clicks for many children. Without this mental model, event bugs look random.
Theory
What bubbles?
Many common events bubble: click, input, change, keydown, and most pointer events. Some events do not bubble or have bubbling alternatives. For example, focus and blur do not bubble, while focusin and focusout do.
Bubble order
For a nested target, the bubble phase runs from the target upward: target, parent, grandparent, and so on. During that journey, event.target stays the original source while event.currentTarget changes for each listener.
Stopping bubbling
Use event.stopPropagation() sparingly. It can be appropriate for nested controls, modals, and menus, but overusing it makes components hard to compose because outer code can no longer observe legitimate events.
Bubbling vs default action
Bubbling is about listener order. It is not the same as default behavior. Calling stopPropagation on a link click does not stop navigation; call preventDefault for that.
Visual Diagrams
root | v capture phase section | v button target phase | ^ section | ^ bubble phase root
Bubbling is the upward half of the event journey, from the target back through ancestors.
button listener then card listener then list listener then page listener
The deepest target handles the bubble phase before its ancestors.
Code Examples
Observe bubbling through nested elements
All three listeners can see the same click. currentTarget changes at each step.
Stop a nested click from reaching ancestors
Use this carefully because it prevents outer components from seeing the event.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1const pathFromTarget = ['button', 'card', 'root'];2let stopped = false;3 4for (const name of pathFromTarget) {5 if (stopped) {6 continue;7 }8 9 console.log(name);10 11 if (name === 'card') {12 stopped = true;13 }14}Coding Exercises
Return the bubbling path
EasyImplement getBubbleOrder(target, parentMap) where parentMap maps a node name to its parent name. Return an array from target to root.
Interview Questions
1What is event bubbling?
Event bubbling is the propagation phase where an event travels from its target up through ancestor nodes. A click on a button can trigger the button listener first, then parent listeners, unless propagation is stopped.
Follow-ups
- How does bubbling enable event delegation?
2Does `stopPropagation` prevent a link from navigating?
No. stopPropagation stops the event from moving to later ancestors. Link navigation is the default action, so it requires preventDefault on a cancelable click event.
Quiz
1. During bubbling, which listener usually runs first for a click inside nested elements?
2. Which method stops the event from reaching later ancestors?
Summary
- Bubbling moves from the event target upward through ancestors.
- `target` stays the original source; `currentTarget` changes as listeners run.
- `stopPropagation` stops later ancestors but does not cancel default action.
- Bubbling is the mechanism that makes event delegation practical.
Cheat Sheet
Bubble path: target → parent → grandparent → root.
Common bubbling events: click, input, change, keydown, pointer events.
Non-bubbling examples: focus, blur (use focusin, focusout when delegation is needed).
Stop: event.stopPropagation().
Remember: stopping propagation is not the same as preventing default action.