When I first started learning JavaScript, one of the most confusing topics was how events actually work inside a browser. Later, during interviews, I realized that the DOM and especially Event Delegation are commonly asked topics.
In this article, I’ll go through the concepts the way I wish someone had explained them to me.
What is the DOM (Document Object Model)?
The DOM is a structured map that the browser uses to interpret and display your webpage.
When you write HTML, the browser turns it into a tree-like structure where each element becomes a node, like <div>, <button>, <p>, etc.
You can think of it like this:
With JavaScript, you and I can manipulate these nodes:
Example:
document.getElementById("title").innerText = "Hello Code Vichar!";
What Problem Does Event Delegation Solve?
Imagine you have a list where items are added dynamically:
<ul id="todoList"></ul>
<button id="addItem">Add Item</button>
Every time a new item is added, you want to detect when the user clicks on it.
A beginner might write:
item.addEventListener("click", () => {
console.log("Item clicked");
});
But this approach has some issues:
- New items added later won’t have the click listener
- Adding many listeners can affect performance
- Managing them all can get messy
This is where Event Delegation makes our lives simple.
What is Event Delegation?
Event Delegation involves adding a single event listener to a parent, allowing it to catch events that originate from its child elements as they rise through the DOM.
Instead of adding a listener to every list item, you add one to the list itself.
Because JavaScript events bubble up, you can detect them at the parent level.
Example (Event Delegation):
const list = document.getElementById("todoList");
list.addEventListener("click", (e) => {
if (e.target && e.target.tagName === 'LI') {
console.log("Item clicked:", e.target.textContent);
}
});
Now it doesn’t matter if:
- Items are static, or
- Items are added later with JavaScript
Everything works automatically. That’s the power of Event Delegation.
How Does Event Delegation Work Under the Hood?
When JavaScript handles events, it processes them in three steps:
- first capturing from the root down to the element,
- then the event happening on the target element itself,
- followed by bubbling the event back up through ancestor elements.
Event Delegation uses the bubbling phase.
So when you click:
<li>Item 1</li>
The flow is:
This means you can detect a click on the list item even if the click started on a nested element.
Example: Dynamic List with Event Delegation (Full Code)
<ul id="todoList"></ul>
<button id="addItem">Add Item</button>
<script>
const addBtn = document.getElementById("addItem");
const list = document.getElementById("todoList");
// Add new item dynamically
addBtn.addEventListener("click", () => {
const li = document.createElement("li");
li.textContent = "New Item " + (list.children.length + 1);
list.appendChild(li);
});
// Event Delegation
list.addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
alert("You clicked: " + e.target.textContent);
}
});
</script>
Event Delegation vs Direct Event Binding
Follow-Up Interview Topics
Interviewers often connect Event Delegation with:
1. Event Bubbling & Capturing
Be ready to explain the three phases of events. To know more refer our post Event Bubbling & Event Capturing.
2. Stop Propagation
Sometimes you want to stop the event from bubbling:
e.stopPropagation();
3. Event.target vs Event.currentTarget
Example:
list.addEventListener("click", (e) => {
console.log("target:", e.target);
console.log("currentTarget:", e.currentTarget);
});
4. Delegation Limitations
Some events, such as blur and focus, do not bubble, so event delegation cannot be used with them effectively.
Best Practices for Event Delegation
- Always check event.target before applying logic
- Use closest() to match nested elements
- Don’t overuse delegation; use it only for repeating or dynamic elements
- Avoid heavy logic inside the delegated listener
- Use class names for target matching
Example using closest():
list.addEventListener("click", (e) => {
const li = e.target.closest("li");
if (li) {
console.log("Clicked item:", li.textContent);
}
});
Conclusion
Event Delegation is one of those smart techniques that makes your frontend cleaner, faster, and more scalable.
Whenever I work with lists, menus, tables, or any dynamic content, I always prefer Event Delegation over attaching multiple listeners.
If you’re preparing for interviews, trust me, this is a topic that comes up often.
Understanding it deeply will give you confidence and help you explain it clearly during any JavaScript or frontend interview.

