Understanding JavaScript Event Propagation: Key Phases Explained

Mitesh KukdejaMitesh Kukdeja
3 min read

Ever clicked on a button inside a card inside a page… and multiple click handlers fired? 🤯 That’s event propagation in action.

Event propagation is how events move through the DOM (Document Object Model) in JavaScript. It follows a well-defined path with three phases:

  1. Capturing Phase
  2. Target Phase
  3. Bubbling Phase

Let’s break them down using simple terms and a real-life analogy. 🔍


📦 Real-Life Analogy: Parcel Delivery

Imagine you order a parcel from Amazon.

  • The parcel first goes to the central warehouse (the root of the DOM)
  • Then to your local delivery hub (parent elements)
  • Finally to your home (target element)
  • You receive it and respond (event fires)
  • Then it returns back through the same route in reverse (bubbling up)

This is exactly how event propagation works in the browser.


🔁 The 3 Phases of Event Propagation

🧭 1. Capturing Phase (Trickling Down)

Analogy: Think of a manager forwarding an important message from the CEO down through all department heads until it reaches the employee concerned.

In the capturing phase, the event starts from the window or document and travels downward to the target element.

parent.addEventListener("click", handler, true); // true = capture phase

The third parameter true tells the browser to listen during the capturing phase.


🎯 2. Target Phase

This is when the event reaches the actual element that was interacted with.

Example: You click a <button> inside a <div>. The target phase is when the event reaches that specific <button>.

At this point, both capture and bubble event listeners on the target will be triggered.

button.addEventListener("click", () => {
  console.log("Button clicked!");
});

🧼 3. Bubbling Phase (Rising Up)

Analogy: Like a ripple effect in water or gossip spreading from a person back up through their social circle.

After the target element processes the event, it bubbles up the DOM tree, triggering any handlers on parent elements.

By default, most event listeners are registered in the bubbling phase:

parent.addEventListener("click", () => {
  console.log("Parent element clicked (bubbling)");
});

This is the most common phase developers work with.


💡 Visual Representation

Document
  ↓   (capturing)
HTMLBODYDIV (Parent)
  ↓
BUTTON (Target) ← Event Triggered HereDIV (Parent)
  ↑   (bubbling)
BODYHTMLDocument

🛑 Stopping Event Propagation

You can stop event propagation at any phase using:

  • event.stopPropagation() → Stops the event from continuing to the next phase

  • event.stopImmediatePropagation() → Stops all listeners on the same element

  • event.preventDefault() → Prevents the default browser behavior (like form submission)

button.addEventListener("click", (event) => {
  event.stopPropagation(); // stops it from bubbling up
  console.log("Button clicked, but event won’t bubble.");
});

🧪 Example in Action

<div id="parent">
  <button id="child">Click me</button>
</div>

Add listeners:

document.getElementById("parent").addEventListener("click", () => {
  console.log("Parent clicked");
});

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

Expected Output on clicking the button:

Child clicked
Parent clicked

Unless stopPropagation() is used, the event bubbles up from #child to #parent.


❗ Why It Matters

  • You can intercept events early (capturing) or let them bubble up
  • Prevent unwanted behaviors using event.stopPropagation()
  • Build advanced UIs like modals, dropdowns, and form validators

✅ Best Practices

  • Default to bubbling unless you have a specific need to capture
  • Always clean up event listeners to avoid memory leaks
  • Be mindful of nesting; bubbling can trigger multiple handlers

🙏 Thank You!

Thank you for reading!

I hope you enjoyed this post. If you did, please share it with your network and stay tuned for more insights on software development. I'd love to connect with you on LinkedIn or have you follow my journey on HashNode for regular updates.

Happy Coding!
Mitesh Kukdeja

1
Subscribe to my newsletter

Read articles from Mitesh Kukdeja directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mitesh Kukdeja
Mitesh Kukdeja

Turning ideas into smooth, scalable mobile experiences — one line of code at a time. Hi, I’m Mitesh Kukdeja — a passionate React Native developer with 2+ years of hands-on experience building cross-platform apps that delight users and deliver results. From health and fitness platforms to job boards and music contest apps, I’ve helped bring a wide range of product visions to life. What sets me apart is my obsession with clean, reusable code and user-centric UI/UX. I specialize in React Native, TypeScript, Redux Toolkit, Firebase, and REST API integration—making sure every app I build is responsive, secure, and ready for scale. I’ve also deployed apps to both the Play Store and App Store, managing the full release cycle. My projects have included integrating real-time features like video conferencing (Agora), personalized push notifications, and advanced security implementations for enterprise clients like Godrej. Whether it’s debugging a performance bottleneck or designing a scalable component architecture, I’m all in. My goal is to keep solving meaningful problems through technology while collaborating with creative minds. I thrive in fast-paced environments where innovation and impact matter. If you’re building something exciting in mobile or looking for a tech partner who values quality and performance — let’s connect!