JavaScript Event eventPhase Property

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Baseline Widely available
Instance property

What You’ll Learn

The eventPhase property is a read-only integer that answers: “Which stage of the event trip am I in?” Learn NONE, CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE—plus how capture listeners differ from bubble ones—with five examples and try-it labs.

01

Kind

Instance property

02

Type

number (0–3)

03

Means

Flow phase now

04

Constants

Event.NONE …

05

Pairs with

capture / bubbles

06

Status

Baseline widely

Introduction

When you click a nested button, the browser does not jump straight to that button and stop. The event travels: down from the window (capture), then at the element that was clicked (target), then back up (bubble) if the event bubbles.

event.eventPhase tells your handler which of those stages is active. Compare it with currentTarget (which listener) and bubbles (whether the trip back up happens).

💡
Beginner tip

Prefer the named constants Event.CAPTURING_PHASE, Event.AT_TARGET, and Event.BUBBLING_PHASE instead of magic numbers 1, 2, and 3.

Understanding Event.eventPhase

An instance property that reports the current evaluation phase of the event flow.

  • Event.NONE (0) — not being processed right now.
  • Event.CAPTURING_PHASE (1) — going down through ancestors (Window → … → parent).
  • Event.AT_TARGET (2) — at the event’s target.
  • Event.BUBBLING_PHASE (3) — going back up (only if bubbles is true).
  • Read-only — the browser sets it during dispatch.
  • Baseline Widely available on MDN (since July 2015); also in Web Workers.

📝 Syntax

JavaScript
event.eventPhase

Value

An integer: 03, matching the Event.* phase constants above.

Typical pattern

JavaScript
const names = ["none", "capturing", "target", "bubbling"];

el.addEventListener("click", (event) => {
  console.log(names[event.eventPhase]);
  // e.g. "target" when this is the clicked element
}, false);

📜 Phase Constants

ConstantValueWhen it is used
Event.NONE0Event is not being processed
Event.CAPTURING_PHASE1Traveling down the ancestor chain
Event.AT_TARGET2At the event target
Event.BUBBLING_PHASE3Traveling back up (if bubbling)

⚡ Quick Reference

GoalCode / note
Read phaseevent.eventPhase
Name it["none","capturing","target","bubbling"][event.eventPhase]
Compareevent.eventPhase === Event.AT_TARGET
Capture listenaddEventListener("click", fn, true)
Bubble listenaddEventListener("click", fn) (default)
MDN statusBaseline Widely available (since July 2015)

🔍 At a Glance

Four facts to remember about Event.eventPhase.

Type
number

0 to 3

Down
1

CAPTURING_PHASE

At target
2

AT_TARGET

Up
3

BUBBLING_PHASE

Examples Gallery

Examples follow MDN Event: eventPhase. Use View Output or Try It Yourself.

📚 Getting Started

Read the phase and highlight when you are at the target.

Example 1 — Map Phase Number to a Name

Log a friendly name for eventPhase on a button click.

JavaScript
const names = ["none", "capturing", "target", "bubbling"];

button.addEventListener("click", (event) => {
  console.log(event.eventPhase);       // usually 2 (AT_TARGET)
  console.log(names[event.eventPhase]); // "target"
});
Try It Yourself

How It Works

A listener on the clicked element itself usually runs during AT_TARGET.

Example 2 — React Only at the Target

Highlight when eventPhase === Event.AT_TARGET (same idea as MDN).

JavaScript
box.addEventListener("click", (event) => {
  if (event.eventPhase === Event.AT_TARGET) {
    event.currentTarget.style.outline = "3px solid tomato";
  }
  console.log("phase:", event.eventPhase);
});
Try It Yourself

How It Works

Parent listeners in bubble mode see phase 3; only the true target sees 2.

📈 Capture & Bubble Chains

Watch phases as the event moves through nested elements.

Example 3 — Bubble Phase on a Parent

Click the child; the parent’s bubble listener reports BUBBLING_PHASE.

JavaScript
parent.addEventListener("click", (event) => {
  console.log(
    event.currentTarget.id,
    event.eventPhase === Event.BUBBLING_PHASE
      ? "bubbling"
      : event.eventPhase
  );
}); // capture defaults to false
Try It Yourself

How It Works

After the child’s target phase, the event bubbles up. Parent bubble listeners see phase 3.

Example 4 — Capture Phase on a Parent

Same tree, but register with true (capture). Phase is 1 on the way down.

JavaScript
parent.addEventListener(
  "click",
  (event) => {
    console.log(
      event.currentTarget.id,
      event.eventPhase === Event.CAPTURING_PHASE
        ? "capturing"
        : event.eventPhase
    );
  },
  true // capture
);
Try It Yourself

How It Works

Capture listeners fire before the target. Useful for intercepting early (for example stopPropagation).

Example 5 — Nested Divs Propagation Log (MDN-style)

Log currentTarget + phase name for each nested box, like MDN’s demo.

JavaScript
const names = ["none", "capturing", "target", "bubbling"];

function onDivClick(event) {
  const level = names[event.eventPhase] ?? "error";
  log.textContent +=
    `${event.currentTarget.id}; eventPhase: ${level}\n`;
}

// bubble mode (false) or capture mode (true)
d1.addEventListener("click", onDivClick, false);
d2.addEventListener("click", onDivClick, false);
d3.addEventListener("click", onDivClick, false);
Try It Yourself

How It Works

Toggle capture in the try-it lab to reverse the order: outer boxes log first with capturing.

🚀 Common Use Cases

  • Teaching / debugging event flow in nested UI.
  • Running logic only at the true target (AT_TARGET).
  • Intercepting early with capture listeners before children run.
  • Confirming whether a parent handler is in bubble or capture mode.
  • Logging analytics that include phase + currentTarget.

🔧 How It Works

1

Capture

Event travels Window → Document → … → parent. Phase = 1.

Down
2

Target

Arrives at the originating element. Phase = 2.

At target
3

Bubble (optional)

If bubbles, travels back up. Phase = 3.

Up
4

Then NONE

After dispatch finishes, eventPhase is 0 again.

📝 Notes

  • MDN: Baseline Widely available (since July 2015) — no Deprecated / Experimental / Non-standard banner.
  • Available in Web Workers.
  • At the target, both capture-registered and bubble-registered listeners see AT_TARGET.
  • If bubbles is false, there is no bubbling phase after the target.
  • Related learning: bubbles, currentTarget, defaultPrevented, addEventListener(), JavaScript hub.

Universal Browser Support

Event.eventPhase is marked Baseline Widely available on MDN (since July 2015). Logos use the shared browser-image-sprite.png sprite from this project. It is also available in Web Workers.

Baseline · Widely available

Event.eventPhase

Read-only integer: which phase of the event flow is being evaluated (0–3).

Universal Widely available
Google Chrome Full support · Desktop & Mobile
Full support
Mozilla Firefox Full support · Desktop & Mobile
Full support
Apple Safari Full support · macOS & iOS
Full support
Microsoft Edge Full support · Chromium
Full support
Opera Full support · Modern versions
Full support
Internet Explorer Supported (legacy)
Full support
Event.eventPhase Excellent

Bottom line: Use eventPhase with capture vs bubble listeners to understand—and debug—the full event trip.

Conclusion

Event.eventPhase reports whether you are in capture, at the target, or bubbling. Pair it with currentTarget, target, and capture options on addEventListener to master DOM event flow.

Continue with explicitOriginalTarget, bubbles, currentTarget, or the JavaScript hub.

💡 Best Practices

✅ Do

  • Compare against Event.AT_TARGET (and friends)
  • Log currentTarget + phase when debugging flow
  • Choose capture only when you need early intercept
  • Remember non-bubbling events skip phase 3
  • Teach capture → target → bubble as one trip

❌ Don’t

  • Assign event.eventPhase yourself
  • Assume every parent listener is bubbling
  • Forget AT_TARGET for both capture and bubble regs on the target
  • Confuse phase with defaultPrevented
  • Rely on magic numbers without comments

Key Takeaways

Knowledge Unlocked

Five things to remember about eventPhase

The stage marker for capture, target, and bubble.

5
Core concepts
⬇️02

Capture

phase 1

Down
🎯03

Target

phase 2

Center
⬆️04

Bubble

phase 3

Up
🎯05

Baseline

since Jul 2015

Status

❓ Frequently Asked Questions

It is a read-only integer on an Event that tells which phase of the event flow is running right now: NONE (0), CAPTURING_PHASE (1), AT_TARGET (2), or BUBBLING_PHASE (3).
No. MDN marks Event.eventPhase as Baseline Widely available (since July 2015). It is not Deprecated, Experimental, or Non-standard. It is also available in Web Workers.
Capture (useCapture true / { capture: true }) runs on the way down from Window toward the target. Bubble (the default) runs on the way back up—only if event.bubbles is true. At the target itself, eventPhase is AT_TARGET for both.
When the event is not being dispatched—for example before or after handlers run, or if you inspect an event object that is not currently flowing through the DOM.
eventPhase tells which stage of the trip you are in. currentTarget tells which element’s listener is running. Together they explain “where in the tree” and “which phase.”
Yes. If bubbles is false, capture still runs, then AT_TARGET, then bubbling is skipped. Processing finishes after the target phase.
Did you know?

Listeners registered on the same target with capture true and false both see eventPhase === Event.AT_TARGET. The capture vs bubble difference shows up on ancestors, not on the target itself.

Next: explicitOriginalTarget

Learn Firefox’s non-standard original target (and why event.target is safer).

explicitOriginalTarget →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful