Skip to main content

Command Palette

Search for a command to run...

Event Bubbling & Event Delegation in JavaScript

Updated
β€’5 min readβ€’View as Markdown

Yesterday, I learned how JavaScript uses events to respond to user interactions.

Today, I went one level deeper and explored how events actually travel through the DOM.

I learned about Event Bubbling, Event Capturing, stopPropagation(), and Event Delegation.

These concepts become extremely useful when working with multiple elements and dynamic content.

Let's dive in.


🌊 What is Event Bubbling?

When an event occurs on an element, it doesn't necessarily stay there.

The event can travel upward through its parent elements.

This process is called Event Bubbling.

For example:

<div id="parent">
    <button id="child">Click Me</button>
</div>

If we click the button, the event can travel:

Button
   ↓
Parent
   ↓
Body
   ↓
HTML
   ↓
Document

This upward movement is event bubbling.


πŸ” Understanding Event Bubbling

Consider:

const parent = document.querySelector("#parent");
const child = document.querySelector("#child");

parent.addEventListener("click", function () {
    console.log("Parent clicked");
});

child.addEventListener("click", function () {
    console.log("Button clicked");
});

When the button is clicked, the output will be:

Button clicked
Parent clicked

The event starts at the button and then bubbles up to its parent.


πŸ›‘ stopPropagation()

Sometimes we don't want an event to continue bubbling.

We can stop it using:

child.addEventListener("click", function (event) {
    event.stopPropagation();

    console.log("Button clicked");
});

Now the event doesn't continue to the parent.

This can be useful when nested elements have different event behavior.


⬇️ Event Capturing

Event capturing is the opposite direction of event bubbling.

Instead of moving from the target upward, the event travels from the document down toward the target.

The general flow is:

Document
   ↓
HTML
   ↓
Body
   ↓
Parent
   ↓
Button

By default, event listeners use the bubbling phase.


Capturing Phase

We can enable capturing by passing true as the third argument.

parent.addEventListener("click", function () {
    console.log("Parent");
}, true);

Now the parent listener runs during the capturing phase.


🎯 Event Target vs Current Target

These two properties are important.

event.target

The element that actually triggered the event.

event.currentTarget

The element whose event listener is currently executing.

Example:

parent.addEventListener("click", function (event) {
    console.log(event.target);
    console.log(event.currentTarget);
});

If the button is clicked:

  • event.target β†’ button

  • event.currentTarget β†’ parent

Understanding this difference becomes very useful with event delegation.


πŸš€ What is Event Delegation?

Event Delegation is a technique where we attach one event listener to a parent instead of adding separate listeners to every child.

For example, instead of:

button1.addEventListener("click", handler);
button2.addEventListener("click", handler);
button3.addEventListener("click", handler);

We can attach one listener to their parent.


Event Delegation Example

HTML:

<ul id="list">
    <li>HTML</li>
    <li>CSS</li>
    <li>JavaScript</li>
</ul>

JavaScript:

const list = document.querySelector("#list");

list.addEventListener("click", function (event) {

    if (event.target.tagName === "LI") {
        console.log(event.target.textContent);
    }

});

Now one event listener handles all the list items.


Why is Event Delegation Useful?

Imagine a shopping cart with 100 products.

Adding a separate event listener to every button isn't always the best approach.

Instead, we can attach one listener to the parent container and determine which child was clicked.

This can make event handling more efficient and easier to manage.


Dynamic Elements

Event delegation becomes especially useful when elements are created dynamically.

For example:

const list = document.querySelector("#list");

const item = document.createElement("li");

item.textContent = "JavaScript";

list.appendChild(item);

Because the listener is attached to the parent, it can handle events from dynamically added children too.


matches() Method

We can use matches() to check whether an element matches a CSS selector.

list.addEventListener("click", function (event) {

    if (event.target.matches("li")) {
        console.log(event.target.textContent);
    }

});

This makes event delegation cleaner and more flexible.


Common Event Handling Concepts

Concept Meaning
Event Bubbling Event travels from child to parent
Event Capturing Event travels from parent to child
stopPropagation() Stops event propagation
event.target Element that triggered the event
event.currentTarget Element handling the event
Event Delegation Parent handles events for its children

Best Practices

βœ” Use event delegation when many similar elements need the same event handling.

βœ” Understand event.target and event.currentTarget.

βœ” Use stopPropagation() only when necessary.

βœ” Avoid unnecessarily attaching hundreds of individual listeners.

βœ” Keep event-handling logic clear and focused.


My Biggest Takeaway

Today, I learned that JavaScript events are more than simply clicking a button.

Events travel through the DOM, and understanding that process gives me much more control over how my applications respond to user interactions.

The concept that stood out the most was Event Delegation.

Instead of attaching listeners to every individual element, I can use a parent element to handle events from its children.

This is a powerful technique that I'll definitely use when building larger and more dynamic applications.

100 Days of Code: My Journey to Becoming a Full Stack Developer

Part 41 of 50

Welcome to my 100 Days of Code journey! In this series, I'll document my daily progress as I learn Full Stack Web Development from the ground up. Every post will cover what I learned, challenges I faced, mistakes I made, and the projects I built. My goal is not just to complete 100 days but to become a better developer through consistency, discipline, and learning in public. Topics I'll cover include: β€’ Git & GitHub β€’ HTML, CSS & JavaScript β€’ React.js β€’ Node.js & Express β€’ MongoDB β€’ APIs β€’ Real-world Projects β€’ AI tools for Developers Whether you're just starting out or revising your fundamentals, I hope this journey helps you learn alongside me. Let's build, learn, and grow together! πŸš€

Up next

Forms & Form Validation in JavaScript

Over the past few days, I've learned how JavaScript interacts with the DOM and responds to user events. Today, I explored Forms and Form Validation. Forms are one of the primary ways users provide inf

More from this blog

T

TheSaurceCode

73 posts

Documenting my journey to becoming a Full Stack Developer through daily blogs, coding challenges, projects, tutorials, and lessons learned. Learn, build, and grow with me