Event Capturing And Event Bubbling In JavaScript

tarunkumar paltarunkumar pal
4 min read

Event propagation, also known as event bubbling and event capturing, refers to the way events are handled and propagated through the DOM (Document Object Model) hierarchy in JavaScript.

When an event occurs on an element in the DOM, such as a button click or a keypress, the event goes through a process called event propagation.

There are three phases of event propagation:

Capturing Phase:- In this phase, the event starts at the top of the DOM hierarchy and propagates down to the target element. During the capturing phase, event handlers attached to ancestor elements are triggered before the event reaches the target element.

Target Phase: Once the event reaches the target element, any event handlers attached to that specific element are executed.

Bubbling Phase: After the target phase, the event propagates back up the DOM hierarchy, triggering event handlers on ancestor elements in reverse order, from the target element up to the top-level element.

we'll create nested HTML Elements and attach an event listener to them.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>

    <div class="grandParent">
        <h2>grandParent</h2>
        <div class="parent">
            <h2>parent</h2>
            <div class="child">
                <h2>child</h2>
            </div>
        </div>
    </div>

    <script src="index.js"></script>

</body>
</html>

index.js


const grandParent = document.getElementById('grandParent');
const parent = document.getElementById('parent');
const child = document.getElementById('child');

grandParent.addEventListener('click', () => {
  console.log('grandParent clicked');
});

parent.addEventListener('click', () => {
  console.log('Parent clicked');
});

child.addEventListener('click', () => {
  console.log('Child clicked');

});

In this example, we have created 3 divs and attached a click event listener on each of them.

addEventListener() sets up a function that will be called whenever the specified event is delivered to the target.

Syntax: target.addEventListener(type, listener [, useCapture]);

  • type: A case-sensitive string representing the event type to listen for.

  • listener: The object that receives a notification (an object that implements the Event interface) when an event of the specified type occurs.

  • useCapture (Optional): A Boolean indicating whether events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.

Event Bubbling

Event bubbling is the default behavior in which an event is first handled by the innermost target element and then propagates upward through its ancestor elements.

In the case of Event bubbling, if you click on child div then it moves up to the hierarchy and goes directly to the start of the DOM.


const grandParent = document.getElementById('grandParent');
const parent = document.getElementById('parent');
const child = document.getElementById('child');

grandParent.addEventListener('click', () => {
  console.log('grandParent clicked');
});

parent.addEventListener('click', () => {
  console.log('Parent clicked');
});

child.addEventListener('click', () => {
  console.log('Child clicked');

});

As shown in the above example, if we click the child div then the event is triggered and it is first handled by the innermost element and then propagated to the outer divs.

Event Capturing

Event capturing is the opposite of event bubbling. In event capturing, the event is first captured by the top-level element and then propagates downward through its descendant elements. However, event capturing is less commonly used compared to event bubbling.


const grandParent = document.getElementById('grandParent');
const parent = document.getElementById('parent');
const child = document.getElementById('child');

grandParent.addEventListener('click', () => {
  console.log('grandParent clicked');
},true);

parent.addEventListener('click', () => {
  console.log('Parent clicked');
},true);

child.addEventListener('click', () => {
  console.log('Child clicked');

},true);

As shown in the above example, whenever you click the child div, the event is first captured by the top element and move down to the target element (an element that triggered the event).

Stop Propagation

Sometimes, you may want to prevent the event from further propagating to ancestor or descendant elements. This can be achieved by calling the stopPropagation() method on the event object within an event handler. This method stops the event from both capturing and bubbling phases.


const grandParent = document.getElementById('grandParent');
const parent = document.getElementById('parent');
const child = document.getElementById('child');

grandParent.addEventListener('click', (event) => {
  console.log('grandParent clicked');
  event.stopPropagation();

});

parent.addEventListener('click', (event) => {
  console.log('Parent clicked');
  event.stopPropagation();

});

child.addEventListener('click', (event) => {
  console.log('Child clicked');
  event.stopPropagation();

});

As you noticed in the above example, when we click on the child div, fthe event is captured by child div, and output is printed to the console but as soon as it encounters e.stopPropagation() it stops further propagation and does not move down to the target element.

0
Subscribe to my newsletter

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

Written by

tarunkumar pal
tarunkumar pal

I'm a recent graduate with a degree in Mechanical Engineering but I have a passion for web development. I have hands on in ReactJS and I have experience building responsive, user-friendly web applications using this framework. I gained hands-on experience in web development through several projects . I'm proficient in HTML, CSS, JavaScript, and I have experience working with various front-end technologies such as ReactJS, Redux, and Bootstrap. I'm also familiar with back-end development such as Node.js and Express.js.