Theme
/
Theory

Events, bubbling, delegation

Lesson 2's card looks good but is dead — clicking does nothing. The DOM runs on events: the browser announces clicks, keys, form submits, and we react to them.

The basics is addEventListener:

button.addEventListener('click', (e) => { /* e — the event object */ });

But the key thing is understanding how events travel. When you click a button inside a card, the event bubbles: it fires on the button first, then the card, then body, then document. One click, several levels up.

From that come two powerful techniques and two traps:

  • Delegation. Instead of a listener on every button, put one on a shared parent. Because events bubble, that single listener sees them all. This is exactly how keyboard shortcuts work (one listener on document).
  • e.stopPropagation() — stops the bubbling. Needed when a button lives inside another clickable element (our ♡ inside the card).
  • e.preventDefault() — stops the browser's default action (a form submit → page reload; a link click → navigation).

stopPropagation and preventDefault are often confused, but they're different: the first stops the event's journey through the DOM, the second stops the browser's built-in reaction. In this lesson we'll see both — and both as real bugs that make the app misbehave.