# Event bubbling and delegation

> Events travel up the tree, so one listener on a parent can handle every child — even ones added later.

Concept · The browser · https://levelcode.org/concepts/event-delegation

When you click a button inside a list item inside a list, the click doesn't stay on the button. A DOM event travels in three phases:

```text
capture:  window → document → … → ul → li     (listeners with { capture: true })
target:   button
bubble:   li → ul → … → document → window      (normal listeners)
```

Most events **bubble**, so a listener on any ancestor hears clicks on its descendants. `event.target` is the element that was actually clicked. `event.currentTarget` is the element whose listener is running.

## Delegation

Instead of attaching a listener to each item, attach one to the container and work out which item was clicked:

```js
list.addEventListener('click', (event) => {
  const button = event.target.closest('button[data-action="delete"]')
  if (!button || !list.contains(button)) return
  removeItem(button.closest('li').dataset.id)
})
```

- **One listener instead of thousands,** so there's less memory and setup.
- **Works for elements added later.** New rows need no wiring, which matters when you render lists from data.
- `closest()` handles clicks on an icon *inside* the button, where `event.target` is the `<svg>` or `<span>`.

React uses this approach internally. It attaches its listeners at the root and dispatches to your components.

## Controlling propagation

- `event.stopPropagation()` stops the event from reaching ancestors. Use it rarely, because it silently breaks delegated listeners, analytics and "click outside to close" handlers further up.
- `event.preventDefault()` cancels the browser's default action, such as following a link or submitting a form. It doesn't stop bubbling, and the two are often confused.
- Some events don't bubble, such as `focus`, `blur`, `mouseenter` and `mouseleave`. Use their bubbling versions, `focusin`, `focusout`, `mouseover` and `mouseout`, for delegation.

## Accessibility

Delegate to real controls. A click listener on a `<div>` works for mouse users, but keyboard and screen-reader users can't reach it. A `<button>` gets focus, Enter and Space handling, and a role for free. See [the accessibility tree](https://levelcode.org/concepts/accessibility-tree).
