Skip to content
GeeksSmith
intermediate 8 min read

Event Bubbling, Capturing, and Event Delegation

Event Delegation is a pattern where a single event listener is attached to a parent element to handle events on its current and future children, leveraging DOM event propagation (bubbling).

Why it matters in interviews

Attaching thousands of individual event listeners to list items or table cells causes severe memory leaks and sluggish DOM insertion. Event delegation reduces memory footprint and automatically handles dynamically inserted DOM nodes.

Visual & Interactive Explanation

DOM Event Propagation Flow (Capturing vs Bubbling)

Sequence & Data Exchange Flow

Window
Document
Body
Button (Target)
#1
WindowDocument
request

1. Capturing Phase begins down DOM hierarchy

#2
DocumentBody
request

2. Capturing traverses down to Parent container

#3
BodyButton (Target)
compute

3. Target Phase: Event fires on clicked Button

#4
Button (Target)Body
response

4. Bubbling Phase: Event bubbles up to Parent (Delegation catches this!)

#5
BodyWindow
response

5. Bubbling finishes at root Window object

Code Examples & Implementation

Vanilla Event Delegation with closest() Pattern
// Single event listener on parent container handles 10,000 product cards
const productGrid = document.querySelector('#product-grid') as HTMLElement;

productGrid.addEventListener('click', (event: MouseEvent) => {
  const target = event.target as HTMLElement;

  // Find closest button with specific data action
  const deleteBtn = target.closest('[data-action="delete"]');
  const buyBtn = target.closest('[data-action="buy"]');

  if (deleteBtn) {
    const card = deleteBtn.closest('.product-card');
    const productId = card?.getAttribute('data-id');
    console.log(`Deleting product ID: ${productId}`);
    return;
  }

  if (buyBtn) {
    const card = buyBtn.closest('.product-card');
    const productId = card?.getAttribute('data-id');
    console.log(`Adding product ID ${productId} to cart`);
  }
});

Interview-Ready Answers

Events in the DOM travel down from Window to the target (capturing) and bubble back up to Window (bubbling). Event delegation places one listener on a parent and uses event.target to identify which child was clicked.

Official Documentation & Specifications

Follow-up Questions & Deep Dives

🎯 Code Output — What Does This Print?

Question 1medium
// HTML: <div id="outer"><div id="inner"><button id="btn">Click</button></div></div>
document.getElementById("outer").addEventListener("click", () => console.log("outer"));
document.getElementById("inner").addEventListener("click", () => console.log("inner"));
document.getElementById("btn").addEventListener("click", () => console.log("btn"));

// User clicks the button. What is the output?
Question 2hard
// HTML: <div id="parent"><button id="child">Click</button></div>
document.getElementById("parent").addEventListener("click", () => console.log("parent"));
document.getElementById("child").addEventListener("click", (e) => {
  console.log("child");
  e.stopPropagation();
});

// User clicks the button. What is the output?
Question 3tricky
// HTML: <ul id="list"><li data-id="1"><span>Item 1</span></li></ul>
document.getElementById("list").addEventListener("click", (e) => {
  console.log("target:", e.target.tagName);
  console.log("currentTarget:", e.currentTarget.tagName);
  const li = e.target.closest("li");
  console.log("data-id:", li?.dataset.id);
});

// User clicks the <span> inside the <li>

Common Mistakes & Anti-Patterns

  • Attaching individual click listeners to every list row in a map loop without considering delegation.
  • Using event.target instead of event.target.closest('selector'), breaking when users click on nested <span> or <i> icons inside a button.
  • Forgetting { passive: true } on scroll and touch listeners, causing scroll lag.

Real-World Architectural Scenario

A table with 10,000 rows causes the browser to freeze for 800ms during initial rendering. Heap analysis shows 30,000 listener closures. How do you resolve this?

Rate Your Readiness

Rate how comfortably you can explain this in an interview to update your global readiness gauge:

Rate your confidence: