JavaScript Academy · Lesson

The Capture and Bubble Phases

Understand how events travel through the DOM.

Lesson 1 of 413 steps

The Capture and Bubble Phases is a free JavaScript Academy lesson on CoddyKit. This is lesson 1 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, and your progress syncs across the web and the CoddyKit app. The JavaScript Academy course includes 4 lessons in total.

Two Trips Through the DOM

When you click an element, the event does not just fire on that element. It travels through the DOM tree in two phases: the capture phase (top down, from document to the target) and the bubble phase (bottom up, from the target back to document).

<div id="outer">
  <button id="inner">Click</button>
</div>

The Default: Bubbling

By default, addEventListener listens during the bubble phase. A click on the inner button fires its handler first, then the handler on its parent, then the grandparent, and so on up to document.

inner.addEventListener("click", () => console.log("inner"));
outer.addEventListener("click", () => console.log("outer"));
// Click inner -> logs: "inner" then "outer"

Opting Into Capture

Pass a third argument of true (or { capture: true }) to listen during the capture phase instead. Capture handlers run top-down, before any bubble handlers.

outer.addEventListener("click", () => console.log("outer capture"), true);
inner.addEventListener("click", () => console.log("inner bubble"));
// Click inner -> "outer capture" then "inner bubble"

The Full Order

For a click on #inner with handlers on both phases, the order is: capture phase top-to-bottom, then the target, then bubble phase bottom-to-top.

  • document capture
  • outer capture
  • inner (target)
  • outer bubble
  • document bubble

event.target vs event.currentTarget

event.target is the element that actually triggered the event (where the click happened). event.currentTarget is the element whose listener is currently running. On a bubbling parent handler these differ.

outer.addEventListener("click", (e) => {
  console.log(e.target.id);        // "inner" - where click occurred
  console.log(e.currentTarget.id); // "outer" - listener owner
});

Stopping Propagation

event.stopPropagation() halts the journey: the event will not continue to the next element in the current phase. Parent handlers higher up the tree never run.

inner.addEventListener("click", (e) => {
  e.stopPropagation();
  console.log("handled here only");
});
outer.addEventListener("click", () => console.log("never runs"));

stopImmediatePropagation

stopPropagation() still lets other listeners on the same element run. To also block sibling listeners on the same element, use event.stopImmediatePropagation().

inner.addEventListener("click", (e) => {
  e.stopImmediatePropagation();
  console.log("first only");
});
inner.addEventListener("click", () => console.log("blocked"));

preventDefault Is Different

Do not confuse preventDefault() with stopPropagation(). preventDefault() cancels the browser default action (following a link, submitting a form) but does NOT stop the event from bubbling.

link.addEventListener("click", (e) => {
  e.preventDefault();  // do not navigate
  // event still bubbles to parents
});

Why Capture Is Rare

Most code uses bubbling because it matches intuition: the specific element reacts first, then containers learn about it. Capture is useful when a parent needs to intercept or veto an event before children see it.

Checking the Phase

event.eventPhase tells you which phase is active: 1 capture, 2 at target, 3 bubble. This is rarely needed but helps when debugging complex listener chains.

el.addEventListener("click", (e) => {
  console.log(e.eventPhase); // 1, 2, or 3
}, true);

Not All Events Bubble

Most UI events (click, input, keydown) bubble. A few do not by default, such as focus, blur, and mouseenter. For those use the bubbling variants (focusin, focusout) or the capture phase.

Quick Check

Test your understanding of event phases.

Recap

Events travel capture (down) then bubble (up). Listeners use bubbling by default; pass true for capture. e.target is the origin, e.currentTarget is the listener owner. Use stopPropagation() to halt travel and preventDefault() to cancel default actions. These two phases are the foundation for event delegation.

Free to start

Learn JavaScript with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
59
Lessons
200

Frequently Asked Questions

Is the “The Capture and Bubble Phases” lesson free?

Yes — any 3 lessons of the JavaScript Academy learning path, including “The Capture and Bubble Phases”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The JavaScript Academy course includes 4 lessons in total.

What will I learn in “The Capture and Bubble Phases”?

Understand how events travel through the DOM. You practise JavaScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start JavaScript Academy?

No prior experience is required. JavaScript Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.

How long does the “The Capture and Bubble Phases” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this JavaScript Academy lesson?

Yes. Every JavaScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. The Capture and Bubble Phases
  2. Event Delegation Pattern
  3. Dynamic Lists with Delegation
  4. Custom Events
← Back to JavaScript Academy