Hello everyone👋, Have you encountered a strange behavior when clicking on the child element. The parent element's click event has also been triggered. Well, this behavior comes under Event propagation.
What is Event propagation?
Event Propagation is the traveling of an event through the DOM(Document Object Model). Every event which has been triggered on a particular element/node travels from the target to the root of the DOM.
Event propagation has two phases
- Bubbling
- Capturing
These two phases can be used on an element but not both at a time. addEventListener() method has three parameters:
- event listener
- callback function
- useCapture
useCapture is an optional parameter. It has a boolean value, by default false. So by default, bubbling is used for event listeners. Except for the focus event listener, which does not use bubbling.
Bubbling
As the name suggests, in this phase the event bubbles from the target to the root element. For example, let's take three nested div elements.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="grand-parent">
<div class="parent">
<div class="child">
</div>
</div>
</div>
</body>
JS
const grandParent=document.querySelector('.grand-parent');
const parent=document.querySelector('.parent');
const child=document.querySelector('.child');
grandParent.addEventListener('click',()=>{
console.log("clicked grand parent element")
},false)
parent.addEventListener('click',()=>{
console.log('cliked parent element');
},false)
child.addEventListener('click',()=>{
console.log("clicked child element");
},false)
Output:
By looking at the output, we can see that suppose if we click on the child element. The click events which are associated with every parent element get triggered.
So the flow of events in bubbling
is from bottom to top.
Capturing
It is the exact opposite of bubbling. The event propagates through the DOM from top to bottom. That is the event travels from the root element to the target element.
Let's see the same example by keeping useCapture
as true.
JS
const grandParent=document.querySelector('.grand-parent');
const parent=document.querySelector('.parent');
const child=document.querySelector('.child');
grandParent.addEventListener('click',()=>{
console.log("clicked grand parent element")
},true)
parent.addEventListener('click',()=>{
console.log('cliked parent element');
},true)
child.addEventListener('click',()=>{
console.log("clicked child element");
},true)
Output:
The click event has been triggered for the same child element. But because of capturing the event propagation started from the root element to the direct element. So every click event element who were enclosing the target element got triggered.
Sometimes, depending on the application, we don't want this event propagation to happen till the root element (bubbling). To avoid this we use the stopPropagation() method.
Conclusion:
Event propagation is a basic and crucial topic in understanding how the event works under the hood.
I hope you enjoyed and understood this article. Feel free to connect with me on Twitter(@rahulmistry751).