A Beginner-Friendly Intro to JavaScript Event Propagation

Search for a command to run...

Thanks for sharing. I am sure, this article will help readers to understand the basics of the event bubbling, propagation, etc..
On a similar note, I was reading about React 17 changes to event delegation recently. You may be interested too. Thought of sharing.
Awesome! Thank you for suggesting! 😄
(This article was primarily written for another blog. The language of this article is more formal. Please let me know your thoughts through the comments.) Writing better and high-quality code is essential. Better code makes software stable and seamle...

This article is going to be a fun one. In this article, we'll be building a Tic Tac Toe game just by using HTML, CSS, and JavaScript. This is going to be an easy one. Both the inputs have to be placed by the user. But in another article, we will be c...

I am sure at some point in your life while browsing the web, you have found a web page that shows an animated counter. A counter that starts from 0 and goes all the way up to some given number. Here is an example of how such a counter looks. In this...

Building a JavaScript project always gives an excellent overview of the internals of the language. And also, it helps to make the portfolio better. In today’s article, we will be building a fantastic mini JavaScript project. We aim to develop a Passw...

Building a Weather app with JavaScript is an excellent project for beginners. It helps to understand the core basics of the DOM and teaches how to use fetch API, to call and get data from a third-party service. In this tutorial, we'll be building a g...

Event propagation is an important concept when dealing with JavaScript events, and it is also crucial in terms of interviews. So, in this article, I'll try to help you understand the concept of Event Propagation.
To put it in easy words,
The parent elements of a child will also receive events that happen to the children.
The easy words seem tough? Don't worry. Let's understand it with example.
<div class="container">
<ul>
<li>
<button>
<a href="#" id="item">Some Text</a>
</button>
</li>
</ul>
</div>
Look at the above snippet. We have a a tag nested inside a button which is inside a list item. Suppose we are clicking the link inside the button. The click will generate a click event for the a tag, and it will start to propagate through all the outer elements. To get a better idea about propagation, let's understand the plain English meaning of the word "propagate". It basically means "transmitting from one generation to another" or "moving from one element to others". So, when I say "it will start to propagate through all the outer elements", it means the event will move from one element to the other.
Event Propagation is the order in which the propagation happens. JavaScript has two types of Event Propagation
Bubbling means that the event propagation will start from the item that was clicked and will bubble up to the root node, starting from the closest one.
Capturing is the opposite of bubbling. It starts from the root element and then propagates by capturing all the child element until it reaches the target element that was clicked.
It is the default event propagation in JavaScript. As we understand earlier, bubbling starts from the element that was clicked and then it propagates all the way, up to the root. To see it in action, let's add some JavaScript to the HTML that we already have.
let item = document.getElementById('item');
let button = document.querySelector('button');
let list = document.querySelector('li');
// Event Bubbling
item.addEventListener('click', (e) => {
console.log('Clicked on the Item');
});
button.addEventListener('click', (e) => {
console.log('Clicked on the Button');
});
list.addEventListener('click', (e) => {
console.log('Clicked on the li');
});
First of all, we are selecting the item id, button and the li Then, we are adding some event handlers to them. We are listening to the click event here. Callback functions are passed to each event handlers, which will console log the text that we are giving each time the event handler listens.
Now, if we click the a tag inside the button, we will see that our console logs out the output in the exact below order.
Clicked on the Item
Clicked on the Button
Clicked on the li
This is happening because the event starts propagating from the item that was clicked to the outer parents. This will bubble up to the root element. But because we do not have any event handlers associated with those, we can't see it.
Now let's see an example of event capturing. The addEventListener can take a third parameter. It is a Boolean value which specifies whether the event capturing is true or false. The default value of the parameter is false. This is the reason why event bubbling happens by default. There can be situations where we want to fire the outer elements first before reaching the origin. So, to implement event capturing, we just have to put the third parameter. And our same above code will be like this -
let item = document.getElementById('item');
let button = document.querySelector('button');
let list = document.querySelector('li');
// Capturing
item.addEventListener(
'click',
(e) => {
console.log('Clicked on the Item');
},
true
);
button.addEventListener(
'click',
(e) => {
console.log('Clicked on the Button');
},
true
);
list.addEventListener(
'click',
(e) => {
console.log('Clicked on the li');
},
true
);
Now, clicking the a tag will console log the output in the exact below order,
Clicked on the li
Clicked on the Button
Clicked on the Item
The capturing starts from the root element and then comes to the origin. Because only the topmost li has an event handler, so it starts logging from the li and comes down to the origin which is the item.
stopPropagation MethodThere may be cases where you don't want the propagation to occur. In such cases, we can use the stopPropagation() method into the callback function to stop it. For example, suppose in our first code, we don't want to propagate the event in the third handler. To prevent the propagation, we specify event.stopPropagation() into the callback of the second handler. Reaching the second handler, the propagation would stop.
let item = document.getElementById('item');
let button = document.querySelector('button');
let list = document.querySelector('li');
// Event Bubbling
item.addEventListener('click', (e) => {
console.log('Clicked on the Item');
});
button.addEventListener('click', (e) => {
console.log('Clicked on the Button');
event.stopPropagation();
});
list.addEventListener('click', (e) => {
console.log('Clicked on the li');
});
If you click on the button now and check the console log, the output will be,
Clicked on the Item
Clicked on the Button
The event stops propagating after reaching the second handler. The same can also be applied for the capturing.
I hope this article helped you to clarify the JavaScript propagation. If this helped you, click the ❤ and leave a comment. You can also follow me on twitter.
Also, check this article about Recursion.