How Event Bubbling Works in the JavaScript DOM

Event bubbling is a core mechanism in the JavaScript Document Object Model (DOM) that dictates how user interactions propagate through nested HTML elements. This article breaks down the mechanics of the event propagation lifecycle, details how bubbling travels upward from the deepest target element to the document root, and explains how developers can leverage event delegation or stop propagation entirely to build efficient web applications.

The Event Propagation Lifecycle

When a user interacts with a web page—such as clicking a button nested inside several <div> tags—the browser does not simply trigger the event on that single element. Instead, the interaction travels through three distinct phases:

  1. The Capturing Phase: The event starts at the window and travels downward through the DOM tree toward the element that triggered the interaction.
  2. The Target Phase: The event reaches the innermost element that was interacted with (represented by event.target).
  3. The Bubbling Phase: The event reverses direction and travels upward from the target element through all its parent nodes until it reaches the window object.

By default, almost all standard browser event listeners registered via addEventListener('click', handler) execute during this third phase: the bubbling phase.

How Bubbling Propagates Through the DOM Tree

Imagine the following HTML structure:

<div id="grandparent">
  <div id="parent">
    <button id="child">Click Me</button>
  </div>
</div>

If a user clicks the <button id="child">, the event bubbling sequence executes as follows:

  1. The browser fires the click event on <button id="child">.
  2. The event bubbles up to <div id="parent">, firing any click listeners attached to it.
  3. The event continues up to <div id="grandparent">, firing its click listeners.
  4. The event propagates further up to <body>, <html>, document, and finally window.

Because of bubbling, a single click on a deeply nested element triggers the event handlers on all ancestor elements in that branch of the DOM tree.

event.target vs. event.currentTarget

Understanding bubbling requires distinguishing between two critical event properties:

During the bubbling phase, event.target remains constant (pointing to the original element), while event.currentTarget changes at each step as the event ascends the tree.

Controlling and Halting Event Bubbling

Developers can intercept and stop the upward propagation of an event using built-in methods provided on the event object:

document.getElementById('child').addEventListener('click', (event) => {
  event.stopPropagation();
  console.log('Button clicked; bubbling stopped.');
});

Practical Application: Event Delegation

The most significant architectural benefit of event bubbling is event delegation. Instead of attaching individual event listeners to dozens or hundreds of child elements (such as list items in a large <ul>), a developer can attach a single listener to a common parent element.

When any child is clicked, the event bubbles up to the parent listener, which inspects event.target to determine which specific item was clicked and executes the appropriate logic. This approach reduces memory consumption and automatically handles dynamically added child elements without requiring new listeners.