The DOM Bubble! What is event bubbling, and how to handle it?

The DOM Bubble! What is event bubbling, and how to handle it?

  • #webdev
  • #javascript
  • #frontend
  • #programming
3 min read

The conecpt:

Event bubbling is a concept in javascript dom where an event propagetes to its parents elements.

The concept of bubbling is similar to how a real bubble works.

Event bubbling with bubble example

How does a bubble works?

Think about a bubble -- it floats up in the air, right? But it doesn't stay up forever. Eventually, it props! It starts samll and grows bigger as it rises.

Event bubbling with water ripple example

Still confused? No worries! Imagine throwing a stone into a pond. The water ripples out from where the stone hit, right? It keeps going until it fades away. In similar way when a click or any other bubbling event trigger it spreads out from the targeted element up-to parents and that's parents until it reaches the root element.

With real example:

Now let's understand by an real example.

Event bubbling with practical example

<body>
  <div class="container">
    <div class="card">
      <button>Button</button>
    </div>
  </div>
</body>

For this html document dom tree will something like:

dom tree example

What happens when the button is clicked?

Clicking on the button first button will trigger the event and that bubble(event) upto its parent card element and then container and finally the body element and as body is the root so it will stop bubbling.

bubbling event through dom tree

It will be more clear if we add event listener.

const body = document.querySelector("body");
const container = document.querySelector(".container");
const card = document.querySelector(".card");
const button = document.querySelector(".card button");

body.addEventListener("click", (e) => {
  alert("body click");
});
container.addEventListener("click", (e) => {
  alert("container click");
});
card.addEventListener("click", (e) => {
  alert("Card click");
});
button.addEventListener("click", (e) => {
  alert("button click");
});

If you click the button, the sequence will be:

- "button click"
- "Card click"
- "container click"
- "body click"

Here if user click on the button it will first tigger button listener and alert button click and then even will pass to its parent card element and alert Card click and then its parent container and alert container click and lastly body and alert body click as these all element have event listener for click event so all of it's parents will be trigger, which you may not want.

event example with bubbling

So now we understand what actaully event bubbling is. Now question is how to prevent it?

Before we stop bubbling, let’s understand that not all events bubble. You can check if an event bubbles like this:

button.addEventListener("click", (e) => {
  event.bubbles; // true if event is bubbling else false
});

Here is a list of bubbling and non-bubbling events

🫧 Bubbling Events:

  • click
  • dblclick
  • mousedown
  • keydown
  • change
  • select
  • ...and many more

🚫 Non-Bubbling Events:

  • focus
  • blur
  • submit
  • reset
  • mouseenter
  • mouseleave
  • ...and many more

How to prevent that propagation?

To stop the event from bubbling, simply call event.stopPropagation().

For example, if we use stop propagtion only in button:

body.addEventListener("click", (e) => {
  alert("body click");
});
container.addEventListener("click", (e) => {
  alert("container click");
});
card.addEventListener("click", (e) => {
  alert("Card click");
});
button.addEventListener("click", (e) => {
  e.stopPropagation();
  alert("button click");
});

after preventing bubbling

it will solve the propagation of click event for button but when click in card it will still propagate to its parent container so if we also don't want that for all then just use stopPropagation

body.addEventListener("click", (e) => {
  e.stopPropagation();
  alert("body click");
});
container.addEventListener("click", (e) => {
  e.stopPropagation();
  alert("container click");
});
card.addEventListener("click", (e) => {
  e.stopPropagation();
  alert("Card click");
});
button.addEventListener("click", (e) => {
  e.stopPropagation();
  alert("button click");
});

Conclusion:

In summary, event bubbling is the default behavior in JavaScript where an event propagates from the targeted DOM element to the root element. This can be useful in many situations, but if you want to stop it, you can use event.stopPropagation().

If this helped you understand the concept, feel free to share, follow, or ask me about any topic you'd like me to cover next!

You can also read: Why Does Event Bubbling Happen by Default? (And Why It Makes Sense)

Here's my LinkedIn profile

Thank you