Skip to main content

Command Palette

Search for a command to run...

JavaScript Event Bubbling and Capturing (Trickling)

Published
β€’3 min read
JavaScript Event Bubbling and Capturing (Trickling)
V

Hi, πŸ‘‹ I'm Vinay Patel I am a Software Developer with a passion for building scalable and high-performance applications.

Event Propagation

JavaScript event propagation occurs in three phases:

  1. Capturing Phase (Trickling) – Events travel from the root (window β†’ document β†’ html β†’ body β†’ ... β†’ target element).

  2. Target Phase – The event reaches the target element where it was originally triggered.

  3. Bubbling Phase – The event propagates back up the DOM (target element β†’ parent β†’ grandparent β†’ document β†’ window).

Event Bubbling

  • Definition: Event bubbling is the default way events propagate in JavaScript. When an event is triggered on an element, it moves upward through the DOM hierarchy to its ancestors.

  • Flow: Events propagate from the target element to its ancestors (child β†’ parent β†’ grandparent β†’ document β†’ window).

  • Key Points:

    • No need to pass a third argument for bubbling; false is the default value.

    • Events "bubble up" like real-world bubbles rising to the surface.

Example Code:

// Event bubbling (default behavior)
document.querySelector("#grandparent").addEventListener(
  "click",
  () => {
    console.log("Grandparent div clicked");
  },
  false // default
);
document.querySelector("#parent").addEventListener(
  "click",
  () => {
    console.log("Parent div clicked");
  },
  false
);
document.querySelector("#child").addEventListener(
  "click",
  () => {
    console.log("Child div clicked");
  },
  false
);

Event Capturing (Trickling)

  • Definition: Event capturing is an alternative propagation method where events travel from the outermost ancestor to the target element.

  • Flow: Events propagate downward through the DOM hierarchy (grandparent β†’ parent β†’ child β†’ target element).

  • Key Points:

    • To enable capturing, pass true as the third argument to addEventListener.

Example Code:

// Event capturing
document.querySelector("#grandparent").addEventListener(
  "click",
  () => {
    console.log("Grandparent div clicked");
  },
  true
);
document.querySelector("#parent").addEventListener(
  "click",
  () => {
    console.log("Parent div clicked");
  },
  true
);
document.querySelector("#child").addEventListener(
  "click",
  () => {
    console.log("Child div clicked");
  },
  true
);

Mixed Propagation Order

  • Behavior: According to W3C standards, capturing happens first, then the target phase, and finally bubbling.

  • Scenarios:

    • true, false, true: Capturing occurs first, then the target phase, and then bubbling begins.

    • true, false, false: Capturing for true listeners, then the target phase, and bubbling for false listeners.

Example Code:

// Mixed propagation order
document.querySelector("#grandparent").addEventListener(
  "click",
  () => {
    console.log("Grandparent div clicked");
  },
  true
);
document.querySelector("#parent").addEventListener(
  "click",
  () => {
    console.log("Parent div clicked");
  },
  false
);
document.querySelector("#child").addEventListener(
  "click",
  () => {
    console.log("Child div clicked");
  },
  true
);

Stopping Event Propagation

  • Method: Use e.stopPropagation() to stop the event from propagating further.

  • Scenarios:

    • Bubbling: Stops propagation from the current element upward.

    • Capturing: Stops propagation before reaching the target element.

Example: Stopping Propagation in Bubbling Phase

// Stopping propagation in bubbling phase
document.querySelector("#grandparent").addEventListener(
  "click",
  () => {
    console.log("Grandparent div clicked");
  },
  false
);
document.querySelector("#parent").addEventListener(
  "click",
  (e) => {
    console.log("Parent div clicked");
    e.stopPropagation(); // Stops event from bubbling further
  },
  false
);
document.querySelector("#child").addEventListener(
  "click",
  (e) => {
    console.log("Child div clicked");
    e.stopPropagation();
  },
  false
);

Example: Stopping Propagation in Capturing Phase

// Stopping propagation in capturing phase
document.querySelector("#grandparent").addEventListener(
  "click",
  (e) => {
    console.log("Grandparent div clicked");
    e.stopPropagation();
  },
  true
);
document.querySelector("#parent").addEventListener(
  "click",
  (e) => {
    console.log("Parent div clicked");
    e.stopPropagation();
  },
  true
);
document.querySelector("#child").addEventListener(
  "click",
  (e) => {
    console.log("Child div clicked");
    e.stopPropagation();
  },
  true
);

Summary

  1. Bubbling: Propagation moves upward from the target element to ancestors.

  2. Capturing: Propagation moves downward from the root to the target element.

  3. Target Phase: The event is at the target element where it was triggered.

  4. Order: Capturing β†’ Target β†’ Bubbling.

  5. Stopping Propagation: e.stopPropagation() halts the event in its current phase.

  6. Best Practices:

    • Use capturing when handling high-level events first.

    • Use bubbling for default behavior and component-based events.

    • Stop propagation only when necessary to avoid unintended side effects.


πŸŽ₯ For More Clarity

Watch this video for a better understanding: Event Bubbling & Capturing Explained

More from this blog

J

Javascript Interview

14 posts