Event Bubbling

Event bubbling is the propagation of an event from its target toward ancestor elements, allowing ancestor listeners to respond to descendant interactions. It is the basis for event delegation, while `stopPropagation()` can prevent further propagation when necessary.

When an event such as a click occurs on a nested element, the browser dispatches it through a propagation path that includes the target and its ancestors. During the bubbling phase, listeners on those ancestors can run after listeners at the target. For example, clicking a button inside a div can invoke click listeners on both the button and the div.

The event's `target` identifies the element where the event originated. `currentTarget` identifies the element whose listener is running at that moment, so it changes as the event reaches different listeners. This distinction is especially useful when one ancestor handles events from many descendants.

Bubbling supports event delegation: attach one listener to a shared parent, then inspect `event.target` (or use `closest()` and verify containment) to determine which child interaction should be handled. This can simplify code for lists and for elements added later, because each child does not need its own listener.

Use `stopPropagation()` only when an event should not continue to ancestor or descendant listeners along its propagation path. It does not cancel the browser's default action, and stopping propagation can interfere with other code that expects to observe the event. Not every event bubbles, so check the behavior of the event type when relying on bubbling.

Key points

Interview questions

A button is nested inside a div, and both have click listeners. What happens when the button is clicked?

After a click on the button, its listener runs at the target and the event then bubbles to the div, where the div listener runs. `event.target` is the button in both listeners because that is where the click originated. `event.currentTarget` is the button in the first listener and the div in the second.

How would you use event bubbling to handle clicks on many list items?

Delegation places one listener on a common ancestor and lets descendant events bubble to it. The handler inspects the target, often with `closest()`, to identify the relevant child and then performs the action. It reduces per-element listener setup and naturally handles matching descendants added after the listener is registered, provided events bubble and the handler checks that the match belongs to the delegated container.

What is the difference between `stopPropagation()` and `preventDefault()`?

`stopPropagation()` prevents the event from continuing along its propagation path, so ancestor listeners that have not yet been reached will not receive it. `preventDefault()` cancels a cancelable event's browser-defined default action, such as a link's navigation, but does not stop the event from reaching other listeners. They address separate behaviors and may be used independently when appropriate.

Explain the difference between event capturing and event bubbling.

Bubbling-phase listeners run as the event moves from the target toward its ancestors. Capture-phase listeners run earlier, as it travels from the outer ancestors toward the target. A listener registered with `addEventListener()` is in the bubbling phase by default; pass a capture option such as `{ capture: true }` to register for capture. The target phase lies between the capture and bubbling traversal, and listener ordering at the target can depend on the capture setting.

A delegated listener is not handling an interaction as expected. What would you investigate?

First verify that the event type bubbles and that the element is actually on the event's propagation path. Then inspect `event.target`, `event.currentTarget`, the listener's capture setting, and whether an earlier handler stopped propagation. If delegation is involved, check whether the target matching logic finds the intended descendant and whether that match is contained by the delegated root. Also account for events whose targets are affected by shadow DOM retargeting.