Understanding JavaScript Event Propagation: Key Phases Explained


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:
- Capturing Phase
- Target Phase
- 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)
HTML
↓
BODY
↓
DIV (Parent)
↓
BUTTON (Target) ← Event Triggered Here
↑
DIV (Parent)
↑ (bubbling)
BODY
↑
HTML
↑
Document
🛑 Stopping Event Propagation
You can stop event propagation at any phase using:
event.stopPropagation()
→ Stops the event from continuing to the next phaseevent.stopImmediatePropagation()
→ Stops all listeners on the same elementevent.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
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!