JavaScript: Guide to Event Bubbling and Capturing

JavaScript: Guide to Event Bubbling and Capturing

Events are the "signal" that represents some action that has happened. In Javascript, such signals can be triggered by DOM events(other types of events also exist like document level, and CSS transitions).

Event handlers can be attached to these nodes which will be executed each time these events occur. But how clicking on child elements triggers the parent node callback or its ancestors if any? Isn't it weird? All of its part of event processing (or how the javascript handles the events). So let's try to understand why it's happening!!

let element=document.querySelector('#content');
element.onclick=function(e){
}
// or by adding using addEventListener method
element.addEventListener(element,function(event){
//callback function
})
//or even in inline style in html directly
<div onclick="alert('clicked')">
<span>Click here</span>
</div>

Bubbling

Event bubbling is the phase of event processing in javascript when an element receives events and starts traversing from its target node to the parent node and reaching the root node in the DOM tree.

Let's say we have 3 nested nodes div -> p -> span and each having the onclick method and clicking on the span will trigger all 3 onclick functions in the following order->

  1. first span onclick will be executed.

  2. then p onclick will be executed.

  3. and in the end div onclick will be executed.

but how we can consume these events and get the actual data we want? few properties come with an event object attached to them.

form.onclick = function(event){ }

event.target -> node from which the event originates.
event.currentTarget -> node which is currently processing the event.

Stop bubbling

Bubbling is the default behaviour for the events and you can override this using the event.stopPropagation(). It can be applied at any level of dom event handler and it will ensure events are not further transmitted to their ancestors. there can be multiple use cases where it can be used like you have the table and you want different onclick behaviour for row and column, In that case, you can stop the bubbling by adding the event.stopPropagation() in the column handler.

Capturing

Event capturing is the initial phase of the event processing where the event traverse from the root node to the target node(closest nested node) which triggers the event and then comes to the event bubbling phase. Though It's rarely used It's better to know about this.

we can enable capturing using the addEventListener method by providing the 3rd parameter like this- By default capturing is set to default.

elem.addEventListener(..., {capture: true}) 
// or simply shorthand property also work for this
elem.addEventListener(...,true)

Now Let's see both capturing and bubbling in action and how they work. below is the link to test out the code and better understand the behaviour.

In the above code, we have three nested elements div->p->span and when you click on most nested elements, the event will be executed in the following order, first capturing and then followed by bubbling.

console output of events

We can also add e.stopPropagation() in the event capturing phase. what do you think it will do? Go and try it yourself in the above code sandbox before proceeding further.

It's going to stop the capturing and bubbling entirely for the rest of the nodes or simply because events go first "down" and then "up" but adding e.stopPropagation() in capturing phase will ensure that no bubbling occurs.

In this article, we learned about DOM events and different phases of event processing like bubbling and capturing. if you find this article helpful and have any suggestions, your valuable feedback is always appreciated.