Suggest an editImprove this articleRefine the answer for “Difference between event.preventdefault() and event.stoppropagation()”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`event.preventDefault()`** cancels the browser's default action for an event. **`event.stopPropagation()`** stops the event from bubbling up to parent elements in the DOM. ```javascript link.addEventListener('click', (e) => { e.preventDefault(); // browser won't navigate to href }); button.addEventListener('click', (e) => { e.stopPropagation(); // parent click handlers won't fire }); ``` **Key point:** they are independent. `stopPropagation` does not prevent browser defaults, and `preventDefault` does not stop bubbling.Shown above the full answer for quick recall.Answer (EN)Image**`preventDefault` vs `stopPropagation`** - one cancels the browser's built-in reaction to an event, the other stops the event from reaching parent elements in the DOM. They are independent, and calling one has zero effect on the other. ## Theory ### TL;DR - `preventDefault()` blocks what the browser does after the event: navigate to a URL, submit a form, show a context menu - `stopPropagation()` blocks where the event goes next: up through parent and ancestor elements - Analogy: `preventDefault` = ignoring a doorbell (the ring happened, but no one opens the door); `stopPropagation` = soundproofing the walls (neighbors never hear it) - `stopPropagation` alone will not prevent a form from submitting. You need `preventDefault` for that. - Decision rule: unwanted browser behavior → `preventDefault`; unwanted handler chain → `stopPropagation` ### Quick example ```javascript document.getElementById('parent').addEventListener('click', () => { console.log('Parent fired'); }); document.getElementById('child').addEventListener('click', (e) => { e.stopPropagation(); // Parent handler won't run console.log('Child fired'); }); // With stopPropagation: "Child fired" only // Without it: "Child fired", then "Parent fired" ``` The parent listener stays silent because `stopPropagation` cuts off the bubble. Calling `preventDefault` here would do nothing since a plain `<button>` inside a `<div>` has no built-in browser action. ### Key difference `preventDefault()` tells the browser to skip its built-in response: don't follow the href, don't reload the page on form submit. The event still travels the DOM normally after this call. `stopPropagation()` cuts off the event's journey so parent handlers never fire, but the browser default still runs unless you also called `preventDefault()`. Two separate flags on the same event object. ### When to use - `<a>` tag with custom routing instead of navigating → `preventDefault` - `<form>` sending data via `fetch` instead of reloading the page → `preventDefault` - A button inside a card where the card also has a click handler → `stopPropagation` on the button - Modal with a backdrop close: clicking inside should not close it → `stopPropagation` on the modal content - Custom dropdown over a link → both, `preventDefault` first ### Comparison table | Aspect | `preventDefault()` | `stopPropagation()` | |---|---|---| | Targets | Browser default action | Event travel through DOM | | DOM traversal | Unaffected, parents still fire | Blocked, parents skip | | Flag set | `event.defaultPrevented = true` | `event.cancelBubble = true` | | Typical use | `<a>` without navigation, form without reload | Modal backdrop, nested card handlers | | Effect on the other | None | None | ### How the browser handles this When an event fires, it travels in three phases: capture (root down to target), target, then bubble (target back up to root). `preventDefault` sets a flag the browser reads after the full dispatch cycle, right before executing its built-in action. `stopPropagation` exits the dispatch loop early so remaining bubble-phase listeners never run. One thing worth knowing: if a parent listener registers with `{ capture: true }`, it fires before any child handler runs. Calling `stopPropagation` in the child does not undo what already fired during capture. ### Common mistakes **Mistake 1: using `stopPropagation` to block a form submit** ```javascript // Wrong: form still submits submitButton.addEventListener('click', (e) => { e.stopPropagation(); }); // Correct submitButton.addEventListener('click', (e) => { e.preventDefault(); }); ``` `stopPropagation` controls event flow, not browser behavior. **Mistake 2: expecting it to block other handlers on the same element** ```javascript elem.addEventListener('click', fn1); elem.addEventListener('click', fn2); // fn2 still runs even if fn1 calls stopPropagation ``` `stopPropagation` only stops the event from reaching other elements. For same-element handlers, use `stopImmediatePropagation()`. **Mistake 3: modal without `stopPropagation` on the content** ```javascript // Bug: any click inside the modal bubbles up to overlay and fires closeModal overlay.addEventListener('click', closeModal); // Fix modalContent.addEventListener('click', (e) => e.stopPropagation()); ``` ### Real-world usage - React: `e.stopPropagation()` in `onClick` for dropdowns and nested components; Vue has `@click.stop` and `@click.prevent` as shorthands - Form handlers in SPAs: `e.preventDefault()` before calling `fetch` - jQuery: `.preventDefault()` and `.stopPropagation()` as separate wrapper calls - Shadow DOM: `stopPropagation` does not cross shadow boundaries by default ### Follow-up questions **Q:** What is the difference between `stopPropagation` and `stopImmediatePropagation`? **A:** `stopPropagation` prevents the event from reaching parent elements, but other handlers on the same element in the same phase still run. `stopImmediatePropagation` blocks both: no more handlers on the current element and no parent handlers either. **Q:** Does `preventDefault` work the same in the capture phase? **A:** Yes. `preventDefault` is phase-independent. The browser checks the flag after the full dispatch cycle, not after each phase. You can call it at any point during the event's journey. **Q:** Can you call `preventDefault` on a custom event? **A:** Yes, if the event was created with `{ cancelable: true }`. Without that flag, `preventDefault` has no effect and `event.defaultPrevented` stays `false`. **Q:** In React, does `e.stopPropagation()` stop native DOM propagation? **A:** No. React uses synthetic events with its own delegation system. `e.stopPropagation()` stops propagation inside React's tree only. To block native DOM propagation, use `e.nativeEvent.stopImmediatePropagation()`. **Q:** In a shadow DOM, does `stopPropagation` cross the shadow boundary? **A:** No. Events are retargeted at shadow boundaries and stay confined to their tree. To pierce the boundary intentionally, dispatch a `CustomEvent` with `{ composed: true }`. ## Examples ### Preventing link navigation ```html <a href="https://example.com" id="link">Go to Example</a> ``` ```javascript document.getElementById('link').addEventListener('click', (e) => { e.preventDefault(); console.log('Link clicked, navigation blocked'); // Page does not change, custom logic runs instead }); ``` The event fired and bubbled normally through the DOM. Only the browser's navigation response was cancelled. Parent elements with click handlers would still receive this event. ### React modal with stopPropagation ```jsx function Modal({ onClose }) { return ( <div className="overlay" onClick={onClose}> <div className="content" onClick={(e) => e.stopPropagation()}> <p>Click here - modal stays open</p> <button onClick={onClose}>Close</button> </div> </div> ); } // Click on .content: stopPropagation prevents bubble to .overlay, onClose does not fire // Click on .overlay directly: onClose fires ``` This is one of the most common patterns for modal components, and forgetting `stopPropagation` on the content div is a bug I have debugged more than once in production. The click travels up to the overlay and closes the modal before the user even realizes what happened.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.