Event Propagation & Delegation

Event Propagation

The event propagation mode determines the order in which elements receive the event.

Event bubbling and Capturing are two ways of event propagation in the HTML DOM API, when an event occurs in an element inside another element, and both elements have registered a handle for that event.

[1]. Bubbling

With bubbling, the event is first captured and handled by the innermost element and then propagated to outer elements.

Relate bubbling to bubbles in a glass of soda.

[2]. Capturing

With capturing, the event is first captured by the outermost element and propagated to the inner elements.

Syntax :

target.addEventListener(type, listener[, useCapture=false]);target.addEventListener("click", callOnClick);

By default, javascript sets the event propagation to Bubble . If we want to useCapture we have to set the 3rd argument in the addEventListener function to true. If NOT specified, useCapture (optional) defaults to false.

The following diagram will give you a further understanding of the event propagation life cycle.

DOM event flow

Not all events bubble

The blur, focus, load and unload events don’t bubble like other events. The blur and focus events can actually be accessed using the capturing phase (in browsers other than IE which still hasn’t compromised on adding a capturing phase) instead of the bubbling phase

What do you think its going to happen when i click the box-3 ? Let’s check it out.

If you had an event bound to browser’s Window, it would be the first to execute. So, in the following example, the order of event handling will be Window, Document, DIV 2, DIV 1, and finally, the button.

Event capturing sample

Omitting or setting the useCapture argument to ‘false’ inside addEventListener() will register events for bubbling. So, the default behavior of Event Listeners is to bubble events.

Event bubbling sample

Stop bubbling to outerMost

The method for it is event.stopPropagation().

For instance, here body.onclick doesn’t work if you click on <button>:


Event Delegation


How JavaScript Event Delegation Works

Event delegation allows you to avoid adding event listeners to specific nodes; instead, the event listener is added to one parent. That event listener analyses bubbled events to find a match on child elements.

Let’s say that we have a parent UL element with several child elements:

<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>

Let’s also say that something needs to happen when each child element is clicked. You could add a separate event listener to each individual LI element, but what if LI elements are frequently added and removed from the list? Adding and removing event listeners would be a nightmare, especially if addition and removal code is in different places within your app. The better solution is to add an event listener to the parent UL element. But if you add the event listener to the parent, how will you know which element was clicked?

Here’s a very basic JavaScript snippet which illustrates event delegation:

// Get the element, add a click listener...document.getElementById("parent-list").addEventListener("click", function(e) {	// e.target is the clicked element!
// If it was a list item
if(e.target && e.target.nodeName == "LI") {
// List item found! Output the ID!
console.log("List item ", e.target.id.replace("post-", ""), " was clicked!");

source: https://javascript.info/bubbling-and-capturing#event-target


A handler on a parent element can always get the details about where it actually happened.

The most deeply nested element that caused the event is called a target element, accessible as event.target.

Note the differences from this (=event.currentTarget):

  • event.target – is the “target” element that initiated the event, it doesn’t change through the bubbling process.
  • this – is the “current” element, the one that has a currently running handler on it.

For instance, if we have a single handler form.onclick, then it can “catch” all clicks inside the form. No matter where the click happened, it bubbles up to <form> and runs the handler.

In form.onclick handler:

  • this (=event.currentTarget) is the <form> element, because the handler runs on it.
  • event.target is the actual element inside the form that was clicked.

NOTE: event delegation is the technique, bubbling is what the event itself does, and capturing is a way of using event delegation on events that don’t bubble.


The preventDefault() restricts the default action that belongs to the event from occurring. Simply put, preventDefault() cancels the event if it is cancelable.

For example, this can be useful when:

  • Clicking on a “Submit” button, prevent it from submitting a form
  • Clicking on a link, prevent the link from following the URL
  • Clicking on a checkbox, prevents the toggling of the checkbox.


Toggling a checkbox is the default action of clicking on a checkbox. The preventDefault() method prevents this from happening.


  • Not all events are cancelable. Use the cancelable property to find out if an event is cancelable.

The preventDefault() method does NOT prevent further propagation of an event through the DOM. Use the stopPropagation() method to handle this.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store