Skip to main content

Event delegation

Event delegation is a JavaScript technique where we attach the handler not to every element but to their common parent, and use event bubbling to determine which element the action actually happened on. In other words: a single listener manages the events of many child elements.

Theory

TL;DR

  • One handler on the parent element instead of a hundred handlers on the children.
  • It works thanks to bubbling: the child's event rises to the parent, which is where it is caught.
  • The specific element is identified through event.target, usually with matches() or closest().
  • It automatically covers elements added to the DOM later.
  • It does not work for events that do not bubble (focus, blur, mouseenter, mouseleave).

Quick example

Say we need to handle clicks on 100 buttons.

The naive way, a listener on every button:

javascript
document.querySelectorAll('button').forEach(btn => { btn.addEventListener('click', () => { console.log('clicked'); }); });

The right way, delegation:

javascript
document.body.addEventListener('click', (event) => { if (event.target.matches('button')) { console.log('clicked'); } });

Why it is worth doing

The key points to name in an interview:

  • Fewer handlers, therefore less memory and a faster page.
  • It works for dynamically added elements: even if an element appeared later, the parent handler still catches it.
  • Better manageability: all the logic lives in one place instead of being smeared across the DOM tree.
  • Easier cleanup: to detach the behaviour you remove one listener instead of walking every node.

How it works

  1. The user clicks a button.
  2. The event bubbles up through the DOM tree.
  3. The handler on body (or on any common ancestor) intercepts the event.
  4. We inspect event.target to identify the candidate element.

A more robust check, for when the button contains nested markup (an icon, a <span>):

javascript
list.addEventListener('click', (event) => { const item = event.target.closest('li'); if (!item || !list.contains(item)) return; console.log('Item clicked:', item.dataset.id); });

closest() walks up from the actual target until it finds a matching element, so a click on an icon inside the item is handled correctly too.

target versus currentTarget

This is the most common interview slip:

  • event.target is the element that was clicked, that is, the source of the event.
  • event.currentTarget is the element the listener is attached to, that is, the parent.
PropertyWhat it points atIn delegation
event.targetThe real target of the eventThe child element we care about
event.currentTargetThe element holding the listenerThe parent container

Inside a regular handler function this equals event.currentTarget, not target.

When delegation is not a fit

  • The event does not bubble. Use focusin and focusout instead of focus and blur, and mouseover and mouseout instead of mouseenter and mouseleave.
  • Someone on the path called stopPropagation(). The event then never reaches the parent listener and delegation silently stops working.
  • Very hot events on a large container. For mousemove or scroll a single handler on document can become the bottleneck; point listeners or throttling are better there.

A short definition, if the interviewer asks for the brief version: event delegation is a technique where one handler on a parent element processes the events of many child elements by relying on event bubbling.

Common mistakes

  • Confusing target with currentTarget, and then wondering why the check always yields the parent container.
  • Checking only event.target.matches(...) where the target can be a nested node. Use closest().
  • Attaching the listener straight to document for no reason. Pick the nearest common ancestor: fewer stray hits and fewer conflicts with other code.
  • Forgetting to verify that the found element really sits inside the container. Without container.contains(item) you can match something from an unrelated block.
  • Counting on delegation for events that do not bubble, and then spending a long time on why the handler never fires.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.