Event propagation in DOM

Divij SehgalDivij Sehgal
3 min read

One of the most important aspects of DOM is understanding how events work. Propagation refers to how events travel through the DOM tree. The event needs to pass through every node on the DOM until it reaches the end, or if it is forcibly stopped.

Event Bubbling and Capturing

The standard DOM Events describes 3 phases of event propagation:

  1. Capturing phase – the event goes down to the element.

  2. Target phase – the event reached the target element.

  3. Bubbling phase – the event bubbles up from the element.

Bubbling

As the name suggests When an event happens on an element, it first runs the handlers on it, then on its parent, and then up on other ancestors. Almost all events bubble. Let's take the standard FORM > DIV > P example:

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

When we click on the P tag, it runs onclick methods on :

  1. The <p> tag

  2. The outer <div> tag

  3. The outer <form> tag

So, we will see three alerts : 'p' -> 'div' -> 'form'.

Some events that do not bubble include focus, blur, load, unload etc.

Stop Bubbling

Bubbling goes from the target element till the document object, but we can stop the bubbling at a certain element by adding event.stopPropagation() to the element. It is advised not to stop bubbling without a real need. For eg:

  • In the case of a nested menu

  • Closing modals by clicking on the negative space

Capturing

Capturing Phase is when the event moves from the top towards the target. Capturing phase is rarely used.

To catch an event, we need to set the capture parameter to true. For ex:

element.addEventListener(..., {capture: true}) 

//Shorthand
element.addEventListener(..., true)

//Default(Bubbling)
element.addEventListener(..., false)

Bubbling and capturing lay the foundation for “event delegation” – an extremely powerful event handling pattern.

Conclusion

When an event happens – the most nested element where it happens gets labelled as the “target element” (event.target).

  • Then the event moves down from the document root to event.target, calling handlers assigned with addEventListener(..., true) on the way (true is a shorthand for {capture: true}).

  • Then handlers are called on the target element itself.

  • Then the event bubbles up from event.target to the root, calling handlers assigned using on<event>, HTML attributes and addEventListener without the 3rd argument or with the 3rd argument false/{capture:false}.

Each handler can access event object properties:

  • event.target – the deepest element that originated the event.

  • event.eventPhase – the current phase (capturing=1, target=2, bubbling=3).

Any event handler can stop the event by calling event.stopPropagation(), but that’s not recommended, because we can’t really be sure we won’t need it above, maybe for completely different things.

The capturing phase is used very rarely, usually, we handle events on bubbling.

Visual Representation

To see a visual representation of how event propagation works, you can check https://domevents.dev/

0
Subscribe to my newsletter

Read articles from Divij Sehgal directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Divij Sehgal
Divij Sehgal