2 min read

Event Bubbling vs. Event Capturing

Event propagation determines the order in which event handlers are executed when an event occurs on a DOM element that is nested inside other elements. There are two main phases: Capturing and Bubbling.

1. The Propagation Flow

When you click a button inside a div, which is inside the body, the event doesn't just happen on the button. It travels through the DOM tree.

The standard DOM Events flow has 3 phases:

  1. Capturing Phase: The event goes down from the window to the element.
  2. Target Phase: The event reaches the target element.
  3. Bubbling Phase: The event bubbles up from the element to the window.

2. Event Bubbling (Default)

In bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.

  • Order: Target -> Parent -> Grandparent -> ... -> Window.
// HTML: <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 clicking button:
// 1. "Child Clicked"
// 2. "Parent Clicked"

Almost all events bubble (exceptions include focus, blur, load, unload).

3. Event Capturing (Trickling)

In capturing, the event is first captured by the outermost element and propagated to the inner elements.

  • Order: Window -> ... -> Grandparent -> Parent -> Target.

To use capturing, you must pass { capture: true } (or just true) as the third argument to addEventListener.

document.getElementById('parent').addEventListener('click', () => {
  console.log('Parent Clicked (Capture)');
}, true); // true enables capturing

document.getElementById('child').addEventListener('click', () => {
  console.log('Child Clicked');
});

// Output when clicking button:
// 1. "Parent Clicked (Capture)"
// 2. "Child Clicked"

4. Stopping Propagation

If you want to stop the event from moving further (either bubbling up or capturing down), use event.stopPropagation().

programming/javascript/vanilla/javascript programming/javascript/vanilla/events programming/javascript/vanilla/dom-manipulation