What is event bubbling and capturing in JavaScript?

HighIntermediateJavascript
Preparing for interviews?

Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.

Quick Answer

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.

Answer

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

addEventListener('click', handler, true)

Target

Actual element clicked

Event fires directly on target

Bubbling

Bottom → Up

From target to document

addEventListener('click', handler) (default)

The three phases of DOM event propagation.

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.

HTML
<div id='parent'>
  <button id='child'>Click Me</button>
</div>
                  
JAVASCRIPT
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 clicked

The 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.

JAVASCRIPT
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 clicked

Now 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.
JAVASCRIPT
child.addEventListener('click', e => {
  e.stopPropagation();
  console.log('Only child handled this.');
});
                  
Still so complicated?

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.
Summary
  • The event path has three phases: capturing → target → bubbling.
  • Bubbling is the default in JavaScript.
  • You can listen in the capturing phase by passing true as the third argument.
  • stopPropagation() prevents the event from continuing.

This knowledge is crucial for efficient event handling and event delegation in complex UIs.

Similar questions
Guides
17 / 61