100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace

What Are Passive Event Listeners and Why Do They Matter?

Learn what passive event listeners are, how { passive: true } removes scroll jank, and when to use them for touch and wheel events.

mediumQ167 of 224 in Web Development Est. time: 5 minsLast updated:
Open Code Lab

Expected Interview Answer

A passive event listener is one registered with `{ passive: true }`, which tells the browser upfront that the handler will never call `preventDefault()`, so the browser can start scrolling immediately instead of waiting for the handler to finish first.

By default, when a user scrolls via touch or wheel, the browser has to wait for every registered touchstart, touchmove, or wheel listener to run to completion before it knows whether the page wants to block the native scroll via `preventDefault()`. If those handlers do any nontrivial work, that wait introduces visible scroll jank, because a synchronous main-thread task is blocking a gesture that should feel instantaneous. Marking a listener as passive is a contract: the browser does not need to wait for the handler because it knows `preventDefault()` will never be called, so it can begin the compositor-thread scroll in parallel with the handler running. This matters most for touchstart, touchmove, and wheel listeners on scrollable containers, and many browsers now default touch listeners to passive in some contexts, but explicit `{ passive: true }` is still best practice for guaranteed behavior across browsers.

  • Lets the browser begin scrolling without waiting for the handler to finish
  • Eliminates a major source of scroll jank on touch and wheel events
  • Signals clear intent that preventDefault will not be called
  • Improves input responsiveness, especially on lower-powered mobile devices

AI Mentor Explanation

A passive event listener is like an umpire pre-declaring that he will never call a boundary review on this delivery, so the ground staff can immediately start resetting the field for the next ball instead of waiting to see if he raises his hand first. Because that promise removes any chance of a stoppage, the next over can begin without delay. If the umpire had not made that promise, the staff would have to pause and wait every single time, just in case. That upfront no-interruption promise is exactly what a passive listener tells the browser about scrolling.

Step-by-Step Explanation

  1. Step 1

    Register the listener with the passive flag

    Pass `{ passive: true }` as the options argument to addEventListener.

  2. Step 2

    Browser reads the contract

    It records that this handler will never call preventDefault() for this event.

  3. Step 3

    Gesture and handler run in parallel

    The compositor thread starts the native scroll immediately while the handler runs on the main thread.

  4. Step 4

    Handler executes without blocking

    Any preventDefault() call inside a passive handler is ignored and logged as a warning.

What Interviewer Expects

  • Clear explanation of why the browser normally waits for handlers before scrolling
  • Correct syntax for registering a passive listener
  • Knowing which events benefit most (touchstart, touchmove, wheel)
  • Awareness that calling preventDefault in a passive listener is a no-op with a console warning

Common Mistakes

  • Marking a listener passive and then still calling preventDefault, expecting it to work
  • Not knowing passive listeners mainly help touch/wheel scroll performance
  • Confusing passive with capture in the options object
  • Assuming passive is the default for all event types in all browsers

Best Answer (HR Friendly)

โ€œPassive event listeners tell the browser upfront that a scroll handler will never try to block the scroll, so the browser can start scrolling immediately instead of waiting to see if the handler cancels it. This removes a common cause of laggy, stuttery scrolling, especially on mobile.โ€

Code Example

Registering a passive scroll listener
// Without passive: browser must wait for the handler before scrolling
container.addEventListener('touchmove', (e) => {
  trackScrollPosition(e)
})

// With passive: browser scrolls immediately, in parallel with the handler
container.addEventListener(
  'touchmove',
  (e) => {
    trackScrollPosition(e)
    // e.preventDefault() here would be ignored and log a warning
  },
  { passive: true }
)

Follow-up Questions

  • What happens if you call preventDefault inside a passive listener?
  • Which event types benefit the most from being marked passive?
  • How do you use the addEventListener options object to combine passive and capture?
  • How would you detect whether the browser supports the passive option?

MCQ Practice

1. What does marking a listener as `{ passive: true }` tell the browser?

Passive is a contract that the handler will not block the default action, like scrolling.

2. Which event types benefit most from being passive?

These scroll-related events are the ones the browser must otherwise wait on before scrolling.

3. What happens if preventDefault() is called inside a passive listener?

The browser ignores the call since it already committed to not waiting, and warns in the console.

Flash Cards

What is a passive event listener? โ€” One registered with { passive: true }, promising it will never call preventDefault().

Why does this help performance? โ€” The browser can start scrolling immediately instead of waiting on the handler.

Best events to mark passive? โ€” touchstart, touchmove, and wheel on scrollable elements.

Effect of preventDefault in a passive listener? โ€” Ignored, with a console warning โ€” it has no effect on the default action.

1 / 4

Continue Learning