Event Propagation
JavaScript event propagation occurs in three phases:
Capturing Phase (Trickling) – Events travel from the root (
window → document → html → body → ... → target element
).Target Phase – The event reaches the target element where it was originally triggered.
Bubbling Phase – The event propagates back up the DOM (
target element → parent → grandparent → document → window
).
Event Bubbling
Definition: Event bubbling is the default way events propagate in JavaScript. When an event is triggered on an element, it moves upward through the DOM hierarchy to its ancestors.
Flow: Events propagate from the target element to its ancestors (child → parent → grandparent → document → window).
Key Points:
No need to pass a third argument for bubbling;
false
is the default value.Events "bubble up" like real-world bubbles rising to the surface.
Example Code:
// Event bubbling (default behavior)
document.querySelector("#grandparent").addEventListener(
"click",
() => {
console.log("Grandparent div clicked");
},
false // default
);
document.querySelector("#parent").addEventListener(
"click",
() => {
console.log("Parent div clicked");
},
false
);
document.querySelector("#child").addEventListener(
"click",
() => {
console.log("Child div clicked");
},
false
);
Event Capturing (Trickling)
Definition: Event capturing is an alternative propagation method where events travel from the outermost ancestor to the target element.
Flow: Events propagate downward through the DOM hierarchy (grandparent → parent → child → target element).
Key Points:
- To enable capturing, pass
true
as the third argument toaddEventListener
.
- To enable capturing, pass
Example Code:
// Event capturing
document.querySelector("#grandparent").addEventListener(
"click",
() => {
console.log("Grandparent div clicked");
},
true
);
document.querySelector("#parent").addEventListener(
"click",
() => {
console.log("Parent div clicked");
},
true
);
document.querySelector("#child").addEventListener(
"click",
() => {
console.log("Child div clicked");
},
true
);
Mixed Propagation Order
Behavior: According to W3C standards, capturing happens first, then the target phase, and finally bubbling.
Scenarios:
true
,false
,true
: Capturing occurs first, then the target phase, and then bubbling begins.true
,false
,false
: Capturing fortrue
listeners, then the target phase, and bubbling forfalse
listeners.
Example Code:
// Mixed propagation order
document.querySelector("#grandparent").addEventListener(
"click",
() => {
console.log("Grandparent div clicked");
},
true
);
document.querySelector("#parent").addEventListener(
"click",
() => {
console.log("Parent div clicked");
},
false
);
document.querySelector("#child").addEventListener(
"click",
() => {
console.log("Child div clicked");
},
true
);
Stopping Event Propagation
Method: Use
e.stopPropagation()
to stop the event from propagating further.Scenarios:
Bubbling: Stops propagation from the current element upward.
Capturing: Stops propagation before reaching the target element.
Example: Stopping Propagation in Bubbling Phase
// Stopping propagation in bubbling phase
document.querySelector("#grandparent").addEventListener(
"click",
() => {
console.log("Grandparent div clicked");
},
false
);
document.querySelector("#parent").addEventListener(
"click",
(e) => {
console.log("Parent div clicked");
e.stopPropagation(); // Stops event from bubbling further
},
false
);
document.querySelector("#child").addEventListener(
"click",
(e) => {
console.log("Child div clicked");
e.stopPropagation();
},
false
);
Example: Stopping Propagation in Capturing Phase
// Stopping propagation in capturing phase
document.querySelector("#grandparent").addEventListener(
"click",
(e) => {
console.log("Grandparent div clicked");
e.stopPropagation();
},
true
);
document.querySelector("#parent").addEventListener(
"click",
(e) => {
console.log("Parent div clicked");
e.stopPropagation();
},
true
);
document.querySelector("#child").addEventListener(
"click",
(e) => {
console.log("Child div clicked");
e.stopPropagation();
},
true
);
Summary
Bubbling: Propagation moves upward from the target element to ancestors.
Capturing: Propagation moves downward from the root to the target element.
Target Phase: The event is at the target element where it was triggered.
Order: Capturing → Target → Bubbling.
Stopping Propagation:
e.stopPropagation()
halts the event in its current phase.Best Practices:
Use capturing when handling high-level events first.
Use bubbling for default behavior and component-based events.
Stop propagation only when necessary to avoid unintended side effects.
🎥 For More Clarity
Watch this video for a better understanding: Event Bubbling & Capturing Explained