Event Propagation

Event propagation describes how a browser event travels through the DOM from an outer ancestor toward the target and then back outward. The flow consists of capturing, the target phase, and bubbling.

When an event occurs on an element, the browser determines the event's propagation path through its DOM ancestors. During the capturing phase, the event travels from the top of the document tree toward the target element. A listener registered with `capture: true` can handle the event during this phase.

The target phase occurs when propagation reaches the element where the event originated. Listeners on that element can run here, regardless of whether they were registered for capturing or bubbling. Afterward, if the event supports bubbling, it travels back through ancestors during the bubbling phase.

Most event handlers are registered for bubbling, such as `element.addEventListener("click", handler)`. This lets a parent respond to events originating from its descendants. Event delegation relies on this behavior: one ancestor listener can handle events from many child elements by inspecting `event.target`.

Propagation can be controlled with methods such as `stopPropagation()` and `stopImmediatePropagation()`. The former prevents the event from continuing to other elements along its propagation path, while the latter also prevents remaining listeners on the current element from running.

Key points

Interview questions

How can you stop an event from propagating?

Call `event.stopPropagation()` from the handler. This prevents the event from continuing to other elements in its propagation path. It does not generally prevent other listeners on the same element from running. For that stronger behavior, `stopImmediatePropagation()` is available.

Why might a parent click handler run when a child is clicked?

A click normally bubbles from the clicked element through its ancestors. Therefore, after the child's handler runs, a handler on its parent can also receive the same event. The parent can inspect `event.target` to determine which descendant originated the click. Propagation can be stopped when that behavior is not desired.

What are the phases of event propagation?

The three phases are capturing, target, and bubbling. During capturing, the event moves from outer ancestors toward the element that triggered it. At the target, handlers associated with that element execute. If the event bubbles, it then travels back through the ancestors.

What is the difference between `event.target` and `event.currentTarget`?

`event.target` is the original element that initiated the event. `event.currentTarget` is the element whose listener is currently executing. They can differ when a parent handles an event through bubbling or event delegation.

How does event delegation work?

Event delegation places a listener on a common ancestor instead of registering separate listeners on every child. Because many events bubble, the ancestor receives events originating from descendants. The handler can inspect `event.target` or use methods such as `closest()` to determine which child should be handled. This can simplify dynamic lists because newly added descendants can be handled without attaching another listener.