DEV Community

Cover image for Mastering Event Propagation in JavaScript: Bubbling vs Capturing
Manali Khattar
Manali Khattar

Posted on

Mastering Event Propagation in JavaScript: Bubbling vs Capturing

Events are a core part of JavaScript development. Whether you're building interactive UIs or handling user inputs, understanding event propagation is key to writing clean, maintainable code.

In this post, we’ll explore how events travel through the DOM using bubbling and capturing, the difference between the two, and when to use each.

What is Event Propagation?
Event propagation refers to the order in which event handlers are invoked when an event occurs in the DOM. There are two main phases:

  • Capturing Phase (a.k.a. trickling)
  • Bubbling Phase

Let’s break them down.

Event Bubbling
Event bubbling is the default phase in JavaScript. When an event is triggered on an element, it first runs the handler on the target element, then "bubbles up" to its ancestors.

Example:

If you click a button inside nested divs, the event is handled by the button first, then moves up to its parent, grandparent, and so on.

Event Capturing
In capturing, the event starts at the topmost ancestor and travels down the DOM tree to the target element. You need to explicitly enable capturing by passing true as the third parameter in addEventListener.

<!DOCTYPE html>
<html>
<head>
  <title>Event Propagation Example</title>
</head>
<body>
  <div id="parent">
    <div id="child">
      <button id="button">Click Me</button>
    </div>
  </div>

  <script>
    function parentClick() {
      console.log("Parent clicked");
    }

    function childClick() {
      console.log("Child clicked");
    }

    function buttonClick() {
      console.log("Button clicked");
    }

    var parent = document.getElementById("parent");
    var child = document.getElementById("child");
    var button = document.getElementById("button");

    parent.addEventListener("click", parentClick, true); // Use capturing phase
    child.addEventListener("click", childClick, true); // Use capturing phase
    button.addEventListener("click", buttonClick); // Default: bubbling phase
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Expected Output in Console (on button click):

Parent clicked
Child clicked
Button clicked

Enter fullscreen mode Exit fullscreen mode

Why this order? Because parentClick and childClick use capturing, they execute before the bubbling-phase buttonClick.

When to Use Bubbling vs Capturing

Use Bubbling when:

  • You want parent components to react to child actions.
  • You’re implementing event delegation (e.g., handling clicks from multiple child elements in one parent handler).
  • You want to close a modal when clicking outside of it.

Use Capturing when:

  • You need to intercept an event before it reaches the target.
  • You want to prevent a default action early (e.g., prevent link navigation).
  • You’re building analytics or monitoring tools that listen high up in the DOM.

Stopping Propagation

You can take control of the flow using:

  • event.stopPropagation() – stops the event from bubbling or capturing further.
  • event.stopImmediatePropagation() – stops all other listeners on the same element. Use them wisely to avoid breaking complex interactions.

Final Thoughts

Understanding event propagation helps you build more powerful and optimized JavaScript applications. Whether you're debugging weird event behaviors or designing reusable components, mastering bubbling and capturing gives you a real edge.

Visual Reference

Mastering Event Propagation in JavaScript

Got Questions?
Have you faced tricky situations due to event propagation? Share your story or doubts in the comments — let’s learn together!

Top comments (1)

Collapse
 
rotech profile image
Rotimi Oloruntobi

Link to your WhatsApp

Some comments may only be visible to logged-in visitors. Sign in to view all comments.