← Back to JavaScript Course | Chapter 10: DOM Advanced | Lesson 2 of 8

JS Event Bubbling and Capturing

When you click something, the click travels up through its parents (bubbling) or down from the top (capturing), like ripples in a pond. You can stop the ripple from spreading.
Syntax
javascript
element.addEventListener("click", handler, false);  // bubbling
element.addEventListener("click", handler, true);   // capturing
event.stopPropagation();

Event Bubbling

In bubbling, an event starts at the target and moves upward through its ancestors. This is the default event flow in the DOM and is why a click on a button nested deep inside several containers can also trigger listeners on those outer containers.

उदाहरण: Event Bubbling

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  // Listen for the `click` event on `document.getElementById("outer")` and run the handler when it fires
  document.getElementById("outer").addEventListener("click", () => console.log("Outer (bubbled)"));
  // Listen for the `click` event on `document.getElementById("inner")` and run the handler when it fires
  document.getElementById("inner").addEventListener("click", () => console.log("Inner (target)"));
</script>

Event Capturing

In capturing, the event travels from the outer ancestor toward the target before bubbling back.

Capturing listeners are less commonly used but are registered by passing true (or {capture: true}) as the third argument to addEventListener, running before the target's own listeners fire.

उदाहरण: Event Capturing

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  // Listen for the `click` event on `document.getElementById("outer")` and run the handler when it fires
  document.getElementById("outer").addEventListener("click", () => console.log("Outer (capture)"), true);
  // Listen for the `click` event on `document.getElementById("inner")` and run the handler when it fires
  document.getElementById("inner").addEventListener("click", () => console.log("Inner (target)"));
</script>

Stopping Propagation

stopPropagation prevents an event from continuing to other ancestors. Calling it inside a handler stops the event from reaching any ancestor listeners, which is useful when a nested element needs to fully own a particular interaction.

उदाहरण: Stopping Propagation

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  // Listen for the `click` event on `document.getElementById("outer")` and run the handler when it fires
  document.getElementById("outer").addEventListener("click", () => console.log("Never runs"));
  document.getElementById("inner").addEventListener("click", (e) => {
    // Call `e.stopPropagation()`
    e.stopPropagation();
    // Print "Inner only" to the console
    console.log("Inner only");
  });
</script>

stopImmediatePropagation

stopImmediatePropagation stops the current event and prevents other listeners on the same target from running.

This is a more targeted stop than stopPropagation — it also blocks any other listeners registered on that same exact element for that same event.

उदाहरण: stopImmediatePropagation

javascript
<button id="btn">Click</button>
<script>
  // Declare the constant `btn`, set to `document.getElementById("btn")`
  const btn = document.getElementById("btn");
  btn.addEventListener("click", (e) => {
    // Call `e.stopImmediatePropagation()`
    e.stopImmediatePropagation();
    // Print "First listener" to the console
    console.log("First listener");
  });
  // Listen for the `click` event on `btn` and run the handler when it fires
  btn.addEventListener("click", () => console.log("Never runs"));
</script>

Bubbling and Capturing Together

Knowing both phases helps you control the order in which event listeners run. Together, capturing and bubbling define the full three-phase journey (capture down, target, bubble up) that every DOM event travels through.

उदाहरण: Bubbling and Capturing Together

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  // Listen for the `click` event on `document.getElementById("outer")` and run the handler when it fires
  document.getElementById("outer").addEventListener("click", () => console.log("2: capture"), true);
  // Listen for the `click` event on `document.getElementById("inner")` and run the handler when it fires
  document.getElementById("inner").addEventListener("click", () => console.log("1: target"));
  // Listen for the `click` event on `document.getElementById("outer")` and run the handler when it fires
  document.getElementById("outer").addEventListener("click", () => console.log("3: bubble"));
</script>
Live Example
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.