Passive event listeners

Esakkimuthu E
3 min readJun 30, 2019

--

Passive event listeners are an emerging web standard, new feature shipped in Chrome 51 and Firefox 49 that provide a major potential boost to scroll performance. It enable us to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners.

The Problem

All modern browsers have a threaded scrolling feature to permit scrolling to run smoothly even when expensive JavaScript is running, but this optimization is partially defeated by the need to wait for the results of any touchstart and touchmove handlers, which may prevent the scroll entirely by calling preventDefault() on the event.

Solution: the ‘passive’ option

we can add a new passive option which declares up-front that the listener will never call preventDefault() on the event. If it does, the user agent will just ignore the request, as it already does for events with Event.cancelable=false

addEventListener(document, "touchstart", function(e) {
console.log(e.defaultPrevented); // will be false
e.preventDefault(); // does nothing since the listener is passive
console.log(e.defaultPrevented); // still false
}, Modernizr.passiveeventlisteners ? {passive: true} : false);

If you are try to block the events mainly touchstart, touchmove, touchend, wheel with preventDefault(). chrome shows a warning in the console: [Violation] Added non-passive event listener to a scroll-blocking ‘mousewheel’ event. Consider marking event handler as ‘passive’ to make the page more responsive. you should use the passive option in .addEventListener(), which doesn’t block the event while your listener executes.

el.addEventListener('wheel', funtion(e){
e.preventDefault(); // does nothing since the listener is passive
// some code here...
}, {passive: true});
// we can attach the event with passive option
document.addEventListener("mousewheel", somefunction(), { passive: true });

Passive event listeners will never invoke preventDefault. If we try to invoke preventDefault inside the Passive event listeners. It will throw the error “Unable to preventDefault inside passive event listener due to target being treated as passive.” We can add a new passive option which declares up-front that the listener will never call preventDefault() on the event. If it does, the user agent will just ignore the request

el.addEventListener('wheel', funtion(e){
e.preventDefault(); // does nothing since the listener is passive
// some code here...
}, {passive: false});
// we can attach the event with passive option
document.addEventListener("mousewheel", somefunction(), { passive: false });

Touchstart, touchmove, touchend, wheel one of these events listeners are bound, the browser has to wait for these listener to be executed before the browser can compute the scroll. These events are mainly touchstart, touchmove, touchend, wheel and in theory to some degree keypress and keydown.

The scroll event itself is not one of these events. The scroll event has no default action, that can be prevented by script. This means if you don’t use preventDefault in your touchstart, touchmove, touchend and/or wheel, always use passive event listeners and you should be fine. In case you use preventDefault, check wether you can substitute it with the CSS touch-action property or lower it at least in your DOM tree. In case of wheel listeners you might be able to bind/unbind them on mouseenter/mouseleave.

.classname {
touch-action: none;
}

In case of any other event: It does not make sense to use passive event listeners to improve performance. Most important to note: The scroll event can’t be canceled and therefore it never makes sense to use passive event listeners for scroll. In case of an infinite scrolling view you don’t need touchmove, you only need scroll, so passive event listeners do not even apply.

For more you can refer https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

--

--

Esakkimuthu E

Front End Developer with over eight years of commercial experience, Passionate about front-end architecture, performance, scalable code, and thoughtful design.