Event Methods
Event objects have methods that can change how the browser handles an event.
The most important ones are:
preventDefault()stopPropagation()stopImmediatePropagation()
Use them carefully. They are powerful, but overusing them can make a page harder to understand.
preventDefault()
Some events have default browser behavior.
Examples:
- clicking a link navigates to its
href - submitting a form reloads or navigates the page
- pressing a key in an input types text
- right-clicking opens a context menu
preventDefault() asks the browser not to perform that default action.
const form = document.querySelector("#signup-form");
form.addEventListener("submit", (event) => {
event.preventDefault();
console.log("Handle the form with JavaScript");
});This is common when JavaScript validates or submits a form with fetch.
Preventing Link Navigation
const link = document.querySelector("#confirm-link");
link.addEventListener("click", (event) => {
const confirmed = confirm("Leave this page?");
if (!confirmed) {
event.preventDefault();
}
});Only prevent default behavior when you have a clear reason.
Links should normally navigate, and forms should normally submit unless your code replaces that behavior.
defaultPrevented
You can check whether default behavior has already been prevented.
document.addEventListener("click", (event) => {
if (event.defaultPrevented) {
console.log("Another listener prevented the default action");
}
});This can help when multiple listeners coordinate around the same event.
Cancelable Events
Not every event can be canceled.
element.addEventListener("click", (event) => {
console.log(event.cancelable);
});If event.cancelable is false, calling preventDefault() has no effect.
Passive Listeners and preventDefault
A passive listener promises not to call preventDefault().
window.addEventListener(
"scroll",
(event) => {
// event.preventDefault() is not allowed in a passive listener.
},
{ passive: true }
);Passive listeners can improve scroll performance, but they are not appropriate when you need to block a default action.
stopPropagation()
stopPropagation() stops the event from continuing through the capturing or
bubbling phases.
button.addEventListener("click", (event) => {
event.stopPropagation();
console.log("Button only");
});
panel.addEventListener("click", () => {
console.log("Panel");
});If the button is inside the panel, the panel's bubbling listener will not run
after the button calls stopPropagation().
Use stopPropagation() Carefully
Stopping propagation can break parent-level behavior such as:
- delegated list handlers
- analytics listeners
- outside-click detection
- keyboard or accessibility helpers
Before using it, ask whether a more precise target check would solve the problem.
panel.addEventListener("click", (event) => {
if (event.target.closest(".ignore-panel-click")) {
return;
}
closePanel();
});This often keeps the event flow easier to reason about.
stopImmediatePropagation()
stopImmediatePropagation() is stronger.
It stops the event from reaching other listeners on the same element and also stops further propagation.
button.addEventListener("click", (event) => {
event.stopImmediatePropagation();
console.log("First listener");
});
button.addEventListener("click", () => {
console.log("Second listener will not run");
});Use this rarely. It can make behavior very surprising.
Methods Compared
| Method | What it does |
|---|---|
preventDefault() |
prevents the browser's default action |
stopPropagation() |
stops the event from moving to other elements |
stopImmediatePropagation() |
also stops later listeners on the same element |
These methods solve different problems.
Preventing a form submit does not stop bubbling. Stopping propagation does not prevent a link from navigating.
Summary
Use preventDefault() when you are replacing a default browser action.
Use propagation-stopping methods only when event flow itself is the problem, and prefer careful target checks when they are enough.