Event Bubbling
When you click a button, you also click everything around it. Events travel through the page in a predictable order.
On this page · 5 min · Intermediate
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Intermediate
- Updated
- Oct 27, 2026
Related tutorials
Learning objectives#
- Describe the capture, target and bubble phases
- Listen in the capture phase
- Stop propagation when needed
- Connect bubbling to event delegation
Explanation#
An event travels in three phases: capturing (from document down to the target), target, and bubbling (from the target back up to document).
Listeners run in the bubbling phase by default. Pass { capture: true } to run during capturing instead.
e.stopPropagation() stops the event travelling further. Use it rarely — it can break other code that relies on bubbling.
Bubbling is what makes event delegation possible: a parent hears events from all its children.
Code example: Watching an event travel#
<div id="outer" style="padding:20px;background:#e0e7ff">Outer
<div id="inner" style="padding:20px;background:#c7d2fe">Inner
<button id="btn">Click me</button>
</div>
</div>
<script>
for (const id of ['outer', 'inner', 'btn']) {
document.getElementById(id).addEventListener('click', () => console.log('bubble:', id));
}
document.getElementById('outer').addEventListener('click', () => console.log('capture: outer'), { capture: true });
</script>
(after clicking the button) capture: outer bubble: btn bubble: inner bubble: outer
Step-by-step explanation#
- The capture listener on outer runs first, on the way down.
- The event reaches the button (target).
- It then bubbles up: inner, then outer.
- Clicking the inner box (not the button) would log capture: outer, bubble: inner, bubble: outer.
Real-world use case#
Closing a dropdown when clicking anywhere outside it, and handling clicks for a whole list with one listener.
Common mistakes#
Stopping propagation can break analytics, menus and delegated handlers elsewhere on the page.
focus and blur do not bubble; use focusin and focusout.
Best practices#
- Rely on bubbling for delegation
- Check e.target or closest() instead of stopping propagation
- Use capture only when you must intercept early
- Use focusin/focusout for delegated focus handling
Remember this#
Capture goes DOWN, bubble comes UP — like a diver.
Default listeners hear the bubble on the way up.
Bubbling is the superpower behind event delegation.
Practice exercise#
Your task: Add stopPropagation to the inner listener and predict what is logged when clicking the button.
Show solution
capture: outer
bubble: btn
bubble: inner
(outer’s bubble listener no longer runs)
Mini quiz#
In which phase do listeners run by default?
Want more? Practise all JavaScript MCQs · JavaScript interview questions
My notes#
Saved in this browser.