Event Bubbling and Capturing - Learn like you are 5
Come on, 'Learn like you're 5' is just a phrase — I'm not telling a toy story here! But I promise, if you read through carefully from start to finish, it'll all make sense.
Event bubbling and capturing are two phases of how events propagate (or travel) through the DOM (Document Object Model) when an event is triggered in JavaScript. Now, this statement requires to clear out the concept of event propagation.
Event Propagation
When an event occurs on an element, like a button inside a div, the event doesn't just happen at that button. The event travels through the DOM in a process known as event propagation. This process happens in two main phases:
Event Capturing (also called "trickling")
Event Bubbling
Now, I hope you got the idea. Let's understand both with examples.
Event Bubbling
Event bubbling means that when an event occurs on an element, it first triggers the event handler for that element. Then, it moves upward in the DOM tree to trigger the event handlers of its parent elements, and so on, until it reaches the document
or the root of the DOM tree.
<div id="parent" style="padding: 20px; background-color: lightblue;">
Parent Div
<button id="child">Click Me!</button>
</div>
<script>
document.getElementById('parent').addEventListener('click', function() {
alert('Parent Div Clicked!');
});
document.getElementById('child').addEventListener('click', function(event) {
alert('Button Clicked!');
// event.stopPropagation(); // If you want to stop bubbling, uncomment this line
});
</script>
Example Explanation: When you click the button, the "Button Clicked!" alert shows first because the event is triggered on the button. After that, the event "bubbles" up to the parent div, and you see the "Parent Div Clicked!" alert. This is because the event starts at the button and then goes up to its parent div. So, this process of propagation is called ‘Event Bubbling’.
Event Capturing
Event capturing is the reverse of bubbling. The event starts from the top of the webpage (beginning with the document) and moves down toward the element you interacted with. This means the event handlers for parent elements will be triggered first, and the event will move down to the child element you clicked or interacted with.
<div id="parent" style="padding: 20px; background-color: lightgreen;">
Parent Div
<button id="child">Click Me!</button>
</div>
<script>
document.getElementById('parent').addEventListener('click', function() {
alert('Parent Div Clicked!');
}, true); // 'true' makes this event handler run during the capturing phase
document.getElementById('child').addEventListener('click', function() {
alert('Button Clicked!');
});
</script>
In this case, when you click the button, the "Parent Div Clicked!" alert will show first. Then, the "Button Clicked!" alert will show because the event starts from the document
level, captures (trickles) down to the parent div first, and then reaches the button.
The value true
of the third argument of addEventListener
is the determiner of capturing phase.
Every Event Goes Through 3 Phases
Naturally, every event goes through all three phases:
Capturing phase: The event starts at the top (
document
) and travels down to the target.Target phase: The event reaches the element you interacted with (the target).
Bubbling phase: After reaching the target, the event bubbles back up through the parent elements.
So yes, an event naturally moves through all three phases, but JavaScript gives you control over which phase your event listener will act in.
Even though events go through all three phases, JavaScript’s event listeners are by default attached to the bubbling phase. This means when you add an event listener without specifying anything, it will listen for the event only in the bubbling phase (after the event has reached the target and starts moving up).
When you pass true
as the third argument, you tell JavaScript to listen for the event during the capturing phase (as it travels down the DOM). The event still goes through all phases (capturing, target, and bubbling), but the listener will be triggered during the capturing phase, before the event reaches the target element.
Does the event go from capturing to bubbling when you use true
? No, the event always moves through both capturing and bubbling. When you pass true
, you’re not preventing the bubbling phase. You’re just telling the listener to respond during capturing. The event will continue from capturing to target and then bubbling as usual.
Summary:
All events naturally go through capturing, target, and bubbling phases.
By default, event listeners work during the bubbling phase (after the event reaches the target and moves upward).
When you pass
true
, you’re telling the event listener to trigger during the capturing phase (as the event travels downward).The event still goes through all phases (capturing, target, and bubbling), but your listener decides in which phase to act.
Subscribe to my newsletter
Read articles from Abeer Abdul Ahad directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Abeer Abdul Ahad
Abeer Abdul Ahad
I am a Full stack developer. Currently focusing on Next.js and Backend.