Event bubbling and capturing define the order in which events propagate through the DOM. Bubbling moves upward from the target element to its ancestors, while capturing moves downward from the root to the target.
What is event bubbling and capturing in JavaScript?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
The Core Idea
When an event (like a click) occurs in the DOM, it doesn’t just happen on one element. Instead, it travels through a three-phase path:
- Capturing phase – The event travels from the root of the document down to the target element.
- Target phase – The event occurs on the exact target element.
- Bubbling phase – The event bubbles up from the target element back to the root.
Phase | Direction | Triggered On | Listener Option |
|---|---|---|---|
Capturing | Top → Down | From document to target |
|
Target | — | Actual element clicked | Event fires directly on target |
Bubbling | Bottom → Up | From target to document |
|
Example: Bubbling (Default Behavior)
When you click on a nested element, the event first triggers on the innermost element and then moves upward to its ancestors.
<div id='parent'>
<button id='child'>Click Me</button>
</div>
document.getElementById('parent').addEventListener('click', () => {
console.log('Parent clicked');
});
document.getElementById('child').addEventListener('click', () => {
console.log('Child clicked');
});
Output when you click the button:
Child clicked
Parent clickedThe event starts at the button (target) and bubbles up to the div.
Example: Capturing Phase
If you set the third parameter of addEventListener to true, the handler will fire during the capturing phase instead of bubbling.
document.getElementById('parent').addEventListener('click', () => {
console.log('Parent capturing');
}, true);
document.getElementById('child').addEventListener('click', () => {
console.log('Child clicked');
});
Output when you click the button:
Parent capturing
Child clickedNow the parent reacts first because the event is captured while traveling down the DOM tree.
Stopping Event Propagation
You can stop the event from moving further in either direction using:
event.stopPropagation()→ stops it from continuing up or down.event.stopImmediatePropagation()→ also prevents other handlers on the same element from firing.
child.addEventListener('click', e => {
e.stopPropagation();
console.log('Only child handled this.');
});
Think of event flow like a water drop hitting nested cups:
- Capturing: The water flows from the biggest cup down to the smallest one.
- Target: The drop hits the smallest cup (the clicked element).
- Bubbling: The water splashes back up through the larger cups.
- The event path has three phases: capturing → target → bubbling.
- Bubbling is the default in JavaScript.
- You can listen in the capturing phase by passing
trueas the third argument. stopPropagation()prevents the event from continuing.
This knowledge is crucial for efficient event handling and event delegation in complex UIs.