Unable to preventDefault inside passive event listener due to target being treated as passive

avatar
Borislav Hadzhiev

Last updated: Apr 4, 2024
4 min

banner

# Table of Contents

  1. Unable to preventDefault inside passive event listener due to target being treated as passive
  2. Check if the event is cancelable before calling event.preventDefault()
  3. Try to remove the event.preventDefault() call
  4. Set the touch-action CSS property to none on the element

# Unable to preventDefault inside passive event listener due to target being treated as passive

The error "[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See URL" occurs when you call the event.preventDefault() method in a passive event listener such as touchstart, touchmove or touchcancel.

To solve the error, set the passive property to false in the options object when calling addEventListener().

Here is an example of how the error occurs.

index.js
document.addEventListener('touchstart', event => { event.preventDefault(); console.log('touchstart event'); }); document.addEventListener('touchmove', event => { event.preventDefault(); console.log('touchmove event'); }); document.addEventListener('touchcancel', event => { event.preventDefault(); console.log('touchcancel event'); });

unable to prevent default inside passive event listener

The code for this article is available on GitHub

The error is raised because touch event listeners are passive by default.

In other words, they pass {passive: true} as the third argument to addEventListener().

The change has been made in Chrome version 56 where all touch listeners are set to be passive by default.

When the {passive: true} object is set as the third argument of addEventListener(), then you are telling the browser that the touch event listener will not call event.preventDefault() and the browser can safely perform the scroll without blocking the listener.

One way to resolve the issue is to pass {passive: false} as the third argument to addEventListener().

index.js
document.addEventListener( 'touchstart', event => { event.preventDefault(); console.log('touchstart event'); }, {passive: false}, ); document.addEventListener( 'touchmove', event => { event.preventDefault(); console.log('touchmove event'); }, {passive: false}, ); document.addEventListener( 'touchcancel', event => { event.preventDefault(); console.log('touchcancel event'); }, {passive: false}, );

error no longer shown in console tab

The code for this article is available on GitHub

Note that the {passive: false} object has to be explicitly passed as the third argument to addEventListener().

After Chrome version 56, the following:

index.js
window.addEventListener("touchstart", func);

Is equivalent to the following:

index.js
window.addEventListener("touchstart", func, {passive: true} );

In other words, the {passive: true} object is the default options object that is passed to addEventListener().

This causes calls to event.preventDefault() inside the touch listener functions to be ignored.

# Check if the event is cancelable before calling event.preventDefault()

You can also resolve the error by checking if the event is cancelable before calling event.preventDefault().

index.js
document.addEventListener('touchstart', event => { if (event.cancelable) { event.preventDefault(); } console.log('touchstart event'); }); document.addEventListener('touchmove', event => { if (event.cancelable) { event.preventDefault(); } console.log('touchmove event'); }); document.addEventListener('touchcancel', event => { if (event.cancelable) { event.preventDefault(); } console.log('touchcancel event'); });

check if event is cancelable

The code for this article is available on GitHub

The cancelable property on the event object indicates whether the event can be canceled and prevented as if the event never happened.

If the event is cancelable, the if block runs and we call event.preventDefault().

Otherwise, event.preventDefault() is not called and the error is never raised.

If the event is not cancelable, then its cancelable property will be set to false and the event listener cannot stop the event from occurring.

# Try to remove the event.preventDefault() call

Another thing you can try is to remove the call to event.preventDefault() and make sure that your code still works as expected.

index.js
document.addEventListener('touchstart', event => { console.log('touchstart event'); }); document.addEventListener('touchmove', event => { console.log('touchmove event'); }); document.addEventListener('touchcancel', event => { console.log('touchcancel event'); });

remove call to event prevent default

The code for this article is available on GitHub

If you call event.preventDefault() in your touchstart or touchmove events, then you will prevent scrolling.

However, most often listeners don't call preventDefault() but the browser needs to wait for the event to finish to be sure of that.

This is why Chrome made the touch events passive by default.

Chances are your code will work as intended even if you don't call event.preventDefault() in your touch event listeners.

# Set the touch-action CSS property to none on the element

If you want to prevent all browser scrolling and zooming within an element, set the touch-action CSS property to none on the element.

Here is the HTML for the example.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <style> #box { touch-action: none; } </style> </head> <body> <div id="box"> <h1>bobbyhadz.com</h1> <h1>bobbyhadz.com</h1> <h1>bobbyhadz.com</h1> <h1>bobbyhadz.com</h1> <h1>bobbyhadz.com</h1> <h1>bobbyhadz.com</h1> </div> <script src="index.js"></script> </body> </html>
The code for this article is available on GitHub

And here is the related JavaScript code.

index.js
document.addEventListener('touchstart', event => { event.preventDefault(); console.log('touchstart event'); }); document.addEventListener('touchmove', event => { event.preventDefault(); console.log('touchmove event'); }); document.addEventListener('touchcancel', event => { event.preventDefault(); console.log('touchcancel event'); });

set touch action css property to none

The code for this article is available on GitHub

Notice that we set the touch-action CSS property to none on the div with the id of box.

style.css
#box { touch-action: none; }

The touch-action CSS property sets how an element's region can be manipulated by a touchscreen user.

The the touch-action CSS property is set to none, then the browser handling of all panning and zooming gestures is disabled.

If you have a horizontal carousel, you can also apply touch-action: pan-y pinch-zoom; to it so the user can still scroll vertically and zoom as normal.

style.css
#box { touch-action: pan-y pinch-zoom; }
The code for this article is available on GitHub

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.