Stopping Propagation vs. Preventing Default in JavaScript

Abstract image used to represent Stopping Propagation vs. Preventing Default in JS
Image by JC Gellidon.

In Brief

preventDefault() stops the browser's builtin action, such as following a link or submitting a form. stopPropagation() stops the event travelling through the DOM to parent handlers. They often appear near each other in event code, but they solve different problems and should be chosen for the behaviour you want to control.

stopPropagation() and preventDefault() are often mentioned together, but they solve different problems. One changes how an event travels through the DOM; the other cancels the browser action associated with that event. Mixing them up can hide bugs in delegated handlers or break useful native behaviour.


Understanding Event Propagation

Before diving into stopPropagation, we need to understand how events travel through the DOM. When an event occurs on an element inside another element, it moves through three phases:

  1. Capturing Phase (Trickling Down)

    – The event starts at the top of the document and moves down to the target element.
  2. Target Phase

    – The event reaches the element that triggered it.
  3. Bubbling Phase (Propagating Up)

    – The event moves back up through the ancestor elements.

By default, most event listeners trigger during the bubbling phase. This means that an event on a child element will also activate event handlers on its parent elements unless we stop it.

Interactions may lead to unexpected behaviour if we do not control event propagation, that's what we can avoid by using stopPropagation.


Using stopPropagation to Stop Further Propagation

stopPropagation() prevents the event from continuing further along its propagation path. It does not undo capturephase delivery that has already occurred, stop other listeners on the current target, or prevent the browser's default action.

Consider this example:

document.getElementById("child")?.addEventListener("click", (event) => {
  event.stopPropagation();
  console.log("Child clicked");
});

document.getElementById("parent")?.addEventListener("click", () => {
  console.log("Parent clicked");
});
<div id="parent">
  <button id="child">Click Me</button>
</div>

Without stopPropagation(), clicking the button logs:

Child clicked
Parent clicked

With stopPropagation(), only "Child clicked" is logged, as the event does not reach the parent.

When to Use stopPropagation()

  • Preventing unintended behaviour when multiple event listeners exist on parent elements.
  • Avoiding nested event triggers, such as inside dropdowns, modals, or dynamically loaded content.

However, we should use stopPropagation sparingly. In many cases, properly structuring event handling is a better solution than stopping propagation entirely.


Using preventDefault to Stop Default Behaviour

preventDefault() cancels a browser default action when the event is cancellable and the listener is not passive. The handler may replace that action, perform validation, or simply decide that the default should not happen; replacement is not a requirement.

For example, clicking a link usually navigates to the href location. We can prevent this behaviour:

document.getElementById("myLink")?.addEventListener("click", (event) => {
  event.preventDefault();
  console.log("Navigation prevented");
});
<a id="myLink" href="https://example.com">Go to Example</a>

Clicking the link now prevents navigation whilst still allowing the event to bubble up.

When to Use preventDefault()

  • Preventing form submissions (submit events).
  • Stopping link navigation when handling custom routing logic.
  • Cancelling touch scrolling when the interaction requires it. A passive listener cannot cancel the event; register that specific listener with { passive: false } only when cancellation is needed.

Unlike stopPropagation, preventDefault does not affect event flow. The event still bubbles up or trickles down the DOM as usual.


Can We Use stopPropagation and preventDefault Together?

Yes, in some cases, we may need to use both. Consider a form inside a modal where submitting the form should:

  1. Prevent the form from submitting (preventDefault()).
  2. Stop the submit event from continuing to an ancestor that would accidentally close the modal (stopPropagation()).
document.getElementById("myForm")?.addEventListener("submit", (event) => {
  event.preventDefault();
  event.stopPropagation();
  console.log("Form submission prevented, event not propagated");
});

This cancels the form's default submission and stops further propagation. It does not undo earlier handlers or stop other listeners on the same target.

However, we should only combine these methods when necessary. Often, restructuring event handling or adjusting event delegation is a better approach than blocking propagation and default behaviour outright.


Wrapping Up

preventDefault() concerns a cancellable browser action; stopPropagation() concerns the event's remaining path through the DOM. Neither method changes the other behaviour automatically, which is why using the correct one matters in delegated handlers, links, and forms.

Key Takeaways

  • stopPropagation() prevents an event from continuing further through its propagation path.
  • preventDefault() can cancel a cancellable default action from a nonpassive listener, without stopping propagation.
  • They can be used together when both event flow and default behaviour need to be controlled.
  • In many cases, restructuring event handling is better than stopping propagation outright.

preventDefault() concerns a cancellable browser action and has no cancelling effect in a passive listener. stopPropagation() stops the event travelling further along its path, without stopping other listeners on the current target or cancelling the default action. They solve different problems, and neither is a substitute for clear ownership of the interaction.


Planning a platform change?

I help teams make difficult platform work clearer, from architecture decisions and migrations to launch recovery, performance, and search visibility.