JavaScript in the browser
Event bubbling and event capturing
Learn how event bubbling and capturing control the order DOM event handlers fire in JavaScript, and how to switch to capturing with addEventListener.
Events move through the DOM in two phases: capturing (window down toward the target) and bubbling (target back up toward window).
Suppose your markup is:
<div id="container">
<button>Click me</button>
</div>
You attach one listener on the button and one on #container. A click on the button reaches both unless you stop propagation.
Bubbling (the default) runs the button handler first, then ancestors like #container.
Capturing runs outer handlers before inner ones.
Most events bubble by default. Opt into capture with the third argument to addEventListener:
document.getElementById('container').addEventListener(
'click',
() => {
//window loaded
},
true
)
The full order for one click is: capture phase from window to the target, then target handlers, then bubble phase back up.
Register two listeners on the same button, one with { capture: true } and one without. Click once and read the console order. That single experiment sticks better than any diagram.
Remember that capture runs on the way down and bubbling runs on the way up. Both can fire for the same click when you register handlers in both phases.
Use event.stopPropagation() when a child handler should prevent ancestors from hearing the same event.
Not every DOM event bubbles. focus is a common counterexample. Read event.bubbles in your handler instead of guessing from the event name.
When you debug order issues, log event.eventPhase alongside the handler name. Phase 1 is capture, 2 is target, and 3 is bubble.
Build a tiny page with #container and a nested button, then register one capture listener and one bubble listener. The log order matches what the spec describes.
Default listener registration uses bubbling. You opt into capture explicitly with the third argument or { capture: true }.
Lesson completed