cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Default actions in JavaScript events

Learn when the browser performs built-in event behavior, when preventDefault can cancel it, how passive listeners affect scrolling, and how defaultPrevented coordinates handlers.

You will learn to
  • 01
    Cancel only when it is safeUse preventDefault on cancelable events without confusing it with propagation.
  • 02
    Respect fast scrollingExplain passive listeners, wheel and touch events, and better CSS alternatives.
  • 03
    Coordinate listenersRead defaultPrevented in delegated handlers so one listener can say, 'already handled.'

The browser already has plans

When a user clicks, types, scrolls, submits, or right-clicks, your JavaScript listener is not the only thing in the room. The browser often has a default action: built-in behavior it will perform if nothing cancels it.

A link’s default action is navigation. A form’s default action is submission. A checkbox click toggles its checked state. A printable key in an input inserts a character. Space can scroll the page. These defaults are why plain HTML pages work before you write one line of JavaScript.

The short version

Default actions usually run after event dispatch finishes, unless a listener successfully calls event.preventDefault() on a cancelable event.

Real-life analogyDefault actions are the browser's autopilot

Imagine boarding a plane that already knows the route. Most trips should use autopilot because it is reliable and fast. Sometimes the pilot must take control for a storm. That is preventDefault(): not turning autopilot off forever, just overriding one trip.

In real life: Autopilot follows the usual route
In JavaScript: The browser navigates, submits, toggles, types, or scrolls
In real life: A pilot takes the wheel for this trip
In JavaScript: A listener calls event.preventDefault() for this one event
In real life: The next flight still has autopilot
In JavaScript: Future clicks still have their defaults unless canceled again

Where the analogy stops: Autopilot sounds optional, but many browser defaults are essential accessibility features. Do not take the wheel unless you provide a safe replacement.

This lesson fits after Introduction to events, Bubbling & capturing, and Event delegation. You will use those ideas here: events dispatch through listeners, and later listeners can inspect what earlier listeners did.

preventDefault(): take the wheel

STEP THROUGH

event.preventDefault() requests: “Do not perform the built-in behavior for this event.” The request only succeeds if the event is cancelable. You can check that with event.cancelable.

It does not stop propagation. Other listeners may still run unless you separately call stopPropagation(). It also does not undo behavior that already happened. Default cancellation is about the browser’s next built-in step.

Step through a delegated click
Step 0 of 9Ready
Your turn: follow the blue line

Step through a click that reaches an inner link listener and then an outer delegated router. Switch line 11 to predict whether the router skips.

Running in
  1. script
Next: line 1
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
  type: "click",  cancelable: true,  defaultPrevented: false,  preventDefault() {    if (this.cancelable) this.defaultPrevented = true;  },}; function linkListener(event) {  event.preventDefault();  console.log("link listener finished");} function routerListener(event) {  if (event.defaultPrevented) {    console.log("router skipped");    return;  }  console.log("router handles the click");} linkListener(event);routerListener(event);console.log(event.defaultPrevented);
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Line 10 in the inner listener
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

In the replay, the inner listener can cancel the link default. The outer listener still runs because propagation was not stopped. It simply sees defaultPrevented and decides not to do more.

Autopilot switchboard

INTERACTIVE

The easiest way to understand default actions is to try real ones. This playground attaches listeners with addEventListener inside an effect. The listeners touch only real DOM nodes through refs, so React can keep rendering the lesson safely.

Autopilot switchboard
Switchboard listener shapePop out in the code editor (opens in a new tab)JavaScript
link.addEventListener("click", maybePreventLink);form.addEventListener("submit", maybePreventForm);checkbox.addEventListener("click", maybePreventCheckbox);function maybePrevent(event, switchIsOn) {  if (switchIsOn && event.cancelable) event.preventDefault();  log(event.type, event.defaultPrevented);}

Try real defaults

Link to this lesson’s anchor

Hash: not changed yet

Right-click or long-press this area.
Log
  • Ready. Toggle a switch, then try a browser default.
Try it yourself

Each control is a real browser default. The log reports the event’s cancelable and defaultPrevented values after the listener runs.

Try the same control with prevention on and off. The form targets a hidden frame so you never leave the lesson.

Try these small experiments: allow the link and watch the hash change; prevent the checkbox and notice it refuses to toggle; prevent the input and typed characters do not appear; allow the context menu and the browser may show its real menu.

Fun fact: canceling is not a moral victory

A canceled default should have a replacement. If you block a form submit, show validation or save the data. If you block a context menu, provide your own menu and keyboard access. If you block text selection, make sure copying is not an expected task.

Passive listeners & scrolling

INTERACTIVE

Scrolling is special because it must feel immediate. If every wheel or touchmove listener might cancel scrolling, the browser may have to wait for JavaScript before moving pixels. Passive listeners solve that problem.

Real-life analogyA passive listener is a passenger who promises not to grab the wheel

A passenger may still talk, point, and react. They just promised not to interfere with driving. In JavaScript, a passive listener can log and update state, but it cannot cancel the scroll default.

In real life: Passenger says, 'I will not touch the steering wheel'
In JavaScript: Listener is registered with { passive: true }
In real life: Driver keeps moving without waiting
In JavaScript: The browser can start scrolling immediately
In real life: Passenger reaches anyway; driver ignores it
In JavaScript: Calling preventDefault() is ignored in a passive listener

Where the analogy stops: The browser is not literally driving. Passive is a promise about default cancellation, not about whether your listener can read the event or update UI.

Passive vs non-passive scrolling
The listener option that changes everythingPop out in the code editor (opens in a new tab)JavaScript
box.addEventListener("wheel", (event) => {  log("cancelable", event.cancelable);  if (shouldBlock) {    event.preventDefault();  }  log("defaultPrevented", event.defaultPrevented);}, { passive });

Scrollable test box

Scroll row 1: the browser wants this to move smoothly.

Scroll row 2: the browser wants this to move smoothly.

Scroll row 3: the browser wants this to move smoothly.

Scroll row 4: the browser wants this to move smoothly.

Scroll row 5: the browser wants this to move smoothly.

Scroll row 6: the browser wants this to move smoothly.

Scroll row 7: the browser wants this to move smoothly.

Scroll row 8: the browser wants this to move smoothly.

Scroll row 9: the browser wants this to move smoothly.

Scroll row 10: the browser wants this to move smoothly.

Scroll row 11: the browser wants this to move smoothly.

Scroll row 12: the browser wants this to move smoothly.

Scroll row 13: the browser wants this to move smoothly.

Scroll row 14: the browser wants this to move smoothly.

Log
  • Scroll inside the box with a trackpad or wheel.
Try it yourself

Non-passive mode lets the listener cancel a cancelable wheel or touchmove event, so the box can stop scrolling.

Use this sparingly. CSS touch-action and overscroll-behavior are often better because the browser knows your intent before the event fires.

In modern browsers, a passive listener that calls preventDefault() does not set defaultPrevented. Some browsers also treat touchstart, touchmove, or wheel listeners on window, document, or body as passive by default. Use { passive: false } only when blocking scroll is truly the interaction. CSS touch-action and overscroll-behavior are often better.

defaultPrevented as a sticky note

INTERACTIVE

When preventDefault() succeeds, the event object keeps a boolean sticky note: event.defaultPrevented === true. Later listeners can read it and politely skip their own behavior.

Real-life analogydefaultPrevented is a handled sticky note

The event object is shared as it travels. A child widget can mark the event as handled, and a parent-level router can read that mark without knowing the child’s internal code.

In real life: A teammate sticks 'handled' on a task card
In JavaScript: An inner listener calls preventDefault()
In real life: Another teammate reads the card and does not duplicate work
In JavaScript: A delegated listener checks event.defaultPrevented
In real life: The sticky note stays on that one card
In JavaScript: The flag belongs to this event object only

Where the analogy stops: The sticky note does not say who handled the event or why. If later code needs that detail, pass it through your own state or custom data.

defaultPrevented in a delegated handler
Delegated handler patternPop out in the code editor (opens in a new tab)JavaScript
panel.addEventListener("click", (event) => {  if (event.target.matches("a")) event.preventDefault();});panel.addEventListener("click", (event) => {  if (event.defaultPrevented) return;  runRouterBehavior();});const scroll = new Event("scroll", { cancelable: false });scroll.preventDefault();

Shared event object

Log
  • Click the link-like button, then test the non-cancelable scroll event.
Try it yourself

The outer router does not need to know which inner widget ran. It reads event.defaultPrevented on the shared event object.

The scroll button creates a real Event object without a default action. It demonstrates that cancelable: false keeps defaultPrevented false.

The same idea is common in delegated code: one ancestor listener handles many children, but it backs off when a child has already claimed the default action.

Can this event be canceled?

SORT IT

Not every event can cancel a default. A scroll event is the classic trap: it fires after scrolling happened, so it is not cancelable. If you need to prevent scrolling, cancel the earlier wheel, touchmove, or key event that causes the scroll.

Can you prevent it?
  • Link navigation from a click
  • Form submit from a submit event
  • Checkbox toggling from a click
  • Text selection beginning on mousedown
  • The context menu from contextmenu
  • The scroll event itself
  • Page unload after the page is closing
  • A character inserted by keydown in an input
Try it yourself
0 of 8 correct

Sort each behavior by whether this event is the right place to call preventDefault().

Choose a category for every card. You can change an answer at any time; Reset clears them all.
Which event controls which default?
GoalUsually cancel thisNot this
Stop link navigationThe link's clickA later page-load event
Stop form navigationThe form's submitA click on one submit button only
Stop text insertionA printable keydown or before-input style eventReading the input value afterward
Stop scrollingThe causing wheel, touchmove, or key eventThe scroll event itself
Stop context menucontextmenu in most browsersA random click after the menu opens

Where you will use this

Use default cancellation when you replace the browser’s built-in behavior with an intentional, accessible behavior of your own. Here are three patterns you will see constantly.

Form validation without a reloadPop out in the code editor (opens in a new tab)JavaScript
form.addEventListener("submit", (event) => {  event.preventDefault();  saveWithJavaScript(new FormData(form));});

This submit handler cancels the page navigation, then saves with JavaScript. The replacement behavior must be visible: show loading, success, and error messages.

Keyboard shortcut that blocks one characterPop out in the code editor (opens in a new tab)JavaScript
input.addEventListener("keydown", (event) => {  if (event.key === "x") {    event.preventDefault();  }});

Be careful with keyboard defaults. Users rely on arrows, Tab, Space, Enter, and browser shortcuts. Block only the exact key you replace, and provide another path.

  • Single-page routing

    Cancel a same-origin link click, update history, then render the next view without a full document load.

  • Drawing and maps

    For a canvas or map, carefully cancel gestures the app owns. Use CSS gesture controls when possible.

  • Delegated widgets

    Child widgets can call preventDefault(); parent listeners check defaultPrevented before acting.

Misconceptions and sharp edges

READ BEFORE SHIPPING
  • “preventDefault stops bubbling.” No. It cancels an eligible default action. Propagation is controlled separately.
  • “stopPropagation stops the default.” No. A link can still navigate even if it never reaches an ancestor listener.
  • “return false always works.” Not in addEventListener. Prefer explicit preventDefault().
  • “Passive is just faster syntax.” No. Passive means the listener cannot cancel the default.
  • “Every event has a preventable default.” No. Check event.cancelable and choose the right earlier event.
  • “Blocking defaults is harmless.” Defaults are often accessibility features. Replace them thoughtfully.
The historic return false trapPop out in the code editor (opens in a new tab)JavaScript
button.addEventListener("click", (event) => {  return false; // does not cancel an addEventListener default}); button.onclick = function (event) {  return false; // old property handlers cancel the default};
Four event controls people mix up
ToolWhat it changesWhat it does not change
preventDefault()Eligible browser default behaviorPropagation by itself
stopPropagation()Whether ancestors receive the eventThe default action by itself
{ passive: true }Whether the listener may cancel defaultsWhether the listener may read the event
defaultPreventedReports successful cancellationMakes an event cancelable

Practice

5 EXERCISES
Exercise 1 · Warm-upPredict the delegated click

Write the three console lines in order. Separate them with commas.

Starter codePop out in the code editor (opens in a new tab)JavaScript
const event = { defaultPrevented: false, cancelable: true };
event.preventDefault = function () {
  if (this.cancelable) this.defaultPrevented = true;
};
function linkListener(event) {
  event.preventDefault();
  console.log("link listener finished");
}
function routerListener(event) {
  if (event.defaultPrevented) {
    console.log("router skipped");
    return;
  }
  console.log("router handles the click");
}
linkListener(event);
routerListener(event);
console.log(event.defaultPrevented);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · Warm-upCancelable or not?

    Predict the one console line.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    const scroll = new Event("scroll", { cancelable: false });
    scroll.preventDefault();
    console.log(scroll.defaultPrevented);

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeBlock one typed character

      Which method belongs inside the if block to block the x key?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      input.addEventListener("keydown", (event) => {
        if (event.key === "x") {
          event.preventDefault();
        }
      });

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeFind the bug: the link still navigates

        The developer expected the link not to navigate. Explain the bug, then compare your fix with the solution.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        link.addEventListener("click", (event) => {
          saveDraft();
          return false;
        });
          Exercise 5 · ChallengeDesign a respectful custom menu

          Sketch the event plan for a custom menu in a drawing app. Include the event you cancel and one accessible alternative.

            Check your understanding

            7 QUESTIONS
            Lesson quiz · 7 questionsScore: first tries count
            1. Question 1 of 7When does the browser usually perform a default action for an event?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does the non-cancelable scroll code print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const event = new Event("scroll", { cancelable: false });
              event.preventDefault();
              console.log(event.defaultPrevented);

              Choose an answer to see the explanation.

            3. Question 3 of 7Which statement is true about preventDefault() and propagation?

              Choose an answer to see the explanation.

            4. Question 4 of 7What does the cancelable click code print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const event = new Event("click", { cancelable: true });
              event.preventDefault();
              console.log(event.defaultPrevented);

              Choose an answer to see the explanation.

            5. Question 5 of 7A passive wheel listener calls event.preventDefault(). What should you expect?

              Choose an answer to see the explanation.

            6. Question 6 of 7What does return false do inside a listener added with addEventListener?

              Choose an answer to see the explanation.

            7. Question 7 of 7Why might a delegated router check event.defaultPrevented?

              Choose an answer to see the explanation.

            Key takeaways

            • Default actions are the browser’s built-in behavior for events.
            • preventDefault() works only on cancelable events, and passive listeners cannot cancel.
            • Default actions happen after dispatch finishes, so later listeners can still run and inspect defaultPrevented.
            • Canceling defaults and stopping propagation are different decisions.
            • Respect accessibility: never remove keyboard, scrolling, selection, form, or menu behavior without a clear replacement.

            A default action is the browser’s built-in response to an event, and preventDefault() cancels it only for a cancelable event in a listener allowed to cancel.

            Up next: Custom events.

            CompleteFrontend Clear concepts. Working examples.