Register to get access to free programming courses with interactive exercises

Capturing and bubbling JS: DOM API

Imagine we have two nested elements, each with a click event handler. If you click on an area of an external element that doesn't affect an internal one, then the handler bound to this external element will be executed.

If we click on the inner element, then the outer one will also be clicked on automatically, so both events will occur:

<div>
  <button>Send</button>
</div>
button.addEventListener('click', () => alert('Boom 1!'));
div.addEventListener('click', () => alert('Boom 2!'));

You may wonder in what order these events will happen after clicking the button. In general, an event will pass through the tree from the root, go to the deepest element triggered by the event, and then in the opposite direction.

The journey of an event up and down the tree is called its stages or phases. We will see more about that below.

Capturing

When an event has just occurred, it starts moving through the DOM tree, starting from the root node and going to the deepest one where the event occurred:

               | |
---------------| |---------------
| div          | |              |
|   -----------| |-----------   |
|   | button   \ /          |   |
|   -------------------------   |
|        Event CAPTURING        |
---------------------------------

At the capturing stage, we execute the handlers bound to this stage. The binding is regulated by the third parameter of the addEventListener function:

button.addEventListener('click', () => alert('Boom 1!'), true);
div.addEventListener('click', () => alert('Boom 2!'), true);

The value true binds handlers to the capturing stage. The following output will result:

Boom 2!
Boom 1!

Bubbling

Once the capturing stage ends at the target element, the bubbling stage begins:

               / \
---------------| |---------------
| div          | |              |
|   -----------| |-----------   |
|   | button   | |          |   |
|   -------------------------   |
|        Event BUBBLING         |
---------------------------------

We imply this stage when we call addEventListener without specifying the third parameter:

button.addEventListener('click', () => alert('Boom 1!'));
div.addEventListener('click', () => alert('Boom 2!'));

At this stage, the handlers are executed from the inside out:

Boom 1!
Boom 2!

Why?

Event bubbling is an important part of DOM behavior. Without it, it is impossible to implement events triggered on entire blocks, not just on the deepest elements.

The simplest example is a context menu. Another example could be tables arranged like in Microsoft Excel. These tables are huge, and adding events to each cell would create many identical handlers constantly added as the table grows. Besides the extra code, this strategy slows everything down if you work with many things. It's much easier to put one handler on the whole table.

W3C Model

According to the standard, most events go through both stages, first plunging into the depths of the tree and then rising to the very top. Programmers rarely use the capturing stage, so they hang most handlers on the bubbling one.

In the previous lesson, we saw the e.target object. It is the deepest element that the capture stage goes to.

The target element doesn't change during bubbling. It allows you to find out exactly where the event took place. In addition, the currentTarget object is also available; this is the element the handler is attached to. One or the other is used, depending on the situation:

Event Stages

Usually, the event should bubble to the end, but there are some situations where bubbling is undesirable.

There are two ways to do this:

  • event.stopPropagation() — stops bubbling, but gives all the handlers that are hovering over the current element a chance to refine
  • event.stopImmediatePropagation() — doesn't allow us to execute any more handlers

Let's summarize. Interception is a mechanism for passing an event to a handler. During capturing or bubbling, the event passes from one element to another, and if there is a handler for this event in the element, it gets called.

In other words, the handler intercepts the event. And using the methods described above, we can stop the process of passing an event between elements.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

Bookmate
Health Samurai
Dualboot
ABBYY
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.