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

JS Event Bubbling and Capturing

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.

Example: Event Bubbling

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  document.getElementById("outer").addEventListener("click", () => console.log("Outer (bubbled)"));
  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.

Example: Event Capturing

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  document.getElementById("outer").addEventListener("click", () => console.log("Outer (capture)"), true);
  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.

Example: Stopping Propagation

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  document.getElementById("outer").addEventListener("click", () => console.log("Never runs"));
  document.getElementById("inner").addEventListener("click", (e) => {
    e.stopPropagation();
    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.

Example: stopImmediatePropagation

javascript
<button id="btn">Click</button>
<script>
  const btn = document.getElementById("btn");
  btn.addEventListener("click", (e) => {
    e.stopImmediatePropagation();
    console.log("First listener");
  });
  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.

Example: Bubbling and Capturing Together

javascript
<div id="outer">
  <button id="inner">Click</button>
</div>
<script>
  document.getElementById("outer").addEventListener("click", () => console.log("2: capture"), true);
  document.getElementById("inner").addEventListener("click", () => console.log("1: target"));
  document.getElementById("outer").addEventListener("click", () => console.log("3: bubble"));
</script>
🔒

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.