Go with the Flow: Event Bubbling & Event Capturing

Understanding the phases of Event Propagation

Warren Niu
5 min readNov 28, 2020

As I continue my journey in becoming a Software Engineer, I’ve recently been thrusted back into the world of JavaScript after spending my first couple of months studying Ruby. Enjoying the “magic” of Ruby and it’s emphasis on convention over configuration, I was able to put together some functional applications without truly understanding what happens behind the scenes, assisted by Active Record and the numerous helper methods. I felt like I was on a highway to success of becoming a full-stack developer.

Then JavaScript happened, and the harsh reality of where I’m currently at in my growth and the canyon that I need to cross in order for me to continue my development. The highway has now turned into a rope bridge!

Taking a deep breath, I pressed forward.

Oof…that’s a far drop

Events

After spending some time with DOM manipulation, I was introduced to the concept of a JavaScript “event”. Events, in short, are user actions on the web. Some notable examples of a user event includes a mouse click, a form submission, and a key press.

As developers, it’s important to create the functionality to listen and handle these events (called event listeners & event handlers, conveniently).

This brings us to the topic of this blog. While it’s convention (think about the motto for Ruby above) for many languages to be read from top-to-bottom, left-to-right, understanding how the event flows in JavaScript is one of the many difficult concepts for me to wrap my head around.

Event Propagation

Event Bubbling and Event Capturing are the two phases in which an event propagates in a HTML DOM. Let’s explore them a little further below.

Event Bubbling

Think of a time in your childhood (or adulthood!) when you were blowing bubbles. The joy of watching the bubbles travel in the air and popping it with your finger. Which direction do the bubbles travel?

The principle of Event Bubbling is when an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on the chain of its family tree to the outer-most element. In other words, the element that is most nested is handled first, and then it trickles up all the way until the outer most element.

Let’s use a simple example. Say we are implementing a “click” event, where we’ll be building a response for when a user clicks a “Like” button to increase the like of their favorite player. The HTML would look something like this:

When the user clicks on the button with the class “like-button”, the event bubbles up the tree in the following order:

<button> → <div> → <body>

The event will continue to bubble up past the <body> tag until it reaches the outermost tag.

Stopping the Bubble

I hate to be a party pooper, but let’s say we want to stop the bubbles for our like event. As mentioned above, a bubbling event goes from the target element, which is our inner-most element (in our case, the like button with the class “like-button”) straight up the tree. Normally, the event would go upwards until an <html> tag, and then to a document object, and some events even reaches window, calling all handlers on the path.

But any handler that we use may decide that the event has been fully processed and stop the bubbling prematurely.

This method is called event.stopPropagation().

Using our previous example, you can see that we are using the event.stopPropagation() event on our button. This means that any handlers above the button would not be called.

It’s important to note that if an element has multiple event handlers on a single event, the event.stopPropagation() method will only stop on the event it’s called on, while the other handlers will still execute.

In other words, the method will stop the move upwards, but the other handlers on the event will continue to execute.

To stop the bubbling and prevent ALL handlers on the current element from running, we can use the method event.stopImmediatePropagation().

Event Capturing

Contrary to event bubbling, event capturing is our other method of event process that goes from top down rather than bottom up. Think of the relationship between a predator and a prey. The predator hunts its prey, while the prey (or in this case, a lower predator down the chain) hunts their own prey, and so forth. The event goes down towards the event target, which again, is the inner most element.

While the capturing phrase is rarely used in real code & seemingly invisible, it’s important to understand its role in event propagation.

To catch an event during the capture phase, we need to set the handler capture to “true”. Using the addEventListener method, we can set the third argument as the following:

div.addEventListener(event, handler, {capture: true})

When the user clicks on the button with the class “like-button”, the event captures down the tree in the following order:

<body> → <div> → <button>

Setting the capture value to “true” changes its default behavior and allows the handler to be set on the capturing phase as opposed to the bubbling phase.

Putting it all together

With a basic understanding of the phases of event propagation, we can put it together like the following diagram:

Source: https://vsvaibhav2016.medium.com/event-bubbling-and-event-capturing-in-javascript-6ff38bec30e

When a user clicks our Like button, our button gets labeled as the “Event Target” as it is the inner most nested element, or event.target.

The event then enters into phase one, Event Capturing, and moves down the tree to the event.target — calling handlers that are assigned with {capture: true} as the third argument in our addEventListener method. If all of our handlers have capture argument set to false (our default value), then no events would be handled during this phase.

Once the event reaches the Event Target, the handlers on the target itself will be called.

Finally, the event will bubble up from the target towards the outer most element, calling handlers assigned using a method such as addEventListener without the third capture argument or with the argument set to false.

Conclusion

While I still have quite a ways to cross this canyon called JavaScript, understanding the basics of event propagation and the different phases is an important step for myself & and any aspiring developers to take, and lays the groundwork for other powerful event handlers — such as Event Delegation.

--

--

Warren Niu

Uncovering the truths of Software Engineering one story at a time. Former Healthcare Administrator and proud dad of my Pomeranian, Nami. Based in Brooklyn, NY