Last updated: Apr 4, 2024
Reading time·4 min
event.preventDefault()
event.preventDefault()
calltouch-action
CSS property to none
on the elementThe 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.
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'); });
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()
.
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()
.
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}, );
Note that the {passive: false}
object has to be explicitly passed as the third
argument to addEventListener()
.
After Chrome version 56, the following:
window.addEventListener("touchstart", func);
Is equivalent to the following:
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.
event.preventDefault()
You can also resolve the error by checking if the event is cancelable before
calling event.preventDefault()
.
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'); });
The
cancelable
property on the event
object indicates whether the event can be canceled and
prevented as if the event never happened.
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.
event.preventDefault()
callAnother thing you can try is to remove the call to event.preventDefault()
and
make sure that your code still works as expected.
document.addEventListener('touchstart', event => { console.log('touchstart event'); }); document.addEventListener('touchmove', event => { console.log('touchmove event'); }); document.addEventListener('touchcancel', event => { console.log('touchcancel event'); });
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.
touch-action
CSS property to none
on the elementIf 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.
<!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>
And here is the related JavaScript code.
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'); });
Notice that we set the
touch-action
CSS property to none
on the div
with the id
of box
.
#box { touch-action: none; }
The touch-action
CSS property sets how an element's region can be manipulated
by a touchscreen user.
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.
#box { touch-action: pan-y pinch-zoom; }
You can learn more about the related topics by checking out the following tutorials: