What is event bubbling and how do I stop it?
When an event fires on an element, it does not stay there. It travels down from the document root to the target, then back up through every ancestor. Those two phases are called capturing and bubbling, and handlers attached anywhere along the path will run.
This is why clicking a button inside a card also triggers the card handler, and why a click inside a modal can close it if the close handler is on a parent.
Stopping propagation prevents the event travelling further up, so ancestor handlers do not run. A stronger variant also prevents other handlers on the same element from running, which is worth knowing because it can silently break code someone else attached.
It is worth distinguishing this from preventing the default action, which is a separate thing entirely. That stops the browser built-in behaviour, such as following a link or submitting a form, but does not affect propagation. Confusing the two produces bugs in both directions: a link that still navigates, or a handler that mysteriously never fires.
Stopping propagation is often the wrong fix, because it makes the event invisible to code that had a legitimate reason to see it. Analytics, focus management and outside-click detection all rely on events reaching the document. A more targeted approach is to check whether the event target is actually the element you care about and return early if not.
Bubbling is also genuinely useful rather than merely something to work around. Attaching one handler to a container and identifying which child was clicked is called delegation, and it is more efficient than attaching handlers to hundreds of elements. It also works for elements added later, which individually attached handlers do not.