Passive event listeners may speed up your scroll and touch events

Updated . Posted . Visible to the public.

Scroll and touch event listeners tend to be computationally expensive as they are triggered very often. Every time the event is fired, the browser needs to wait for the event to be processed before continuing - the event could prevent the default behavior. Luckily there is a concept called passive event listeners Show archive.org snapshot which is supported by all modern browsers.

Below are the key parts quoted from WICG's explainer on passive event listeners. See this demo video Show archive.org snapshot for a side-by-side comparison.

While there are particular scenarios where an author may indeed want to prevent scrolling, analysis indicates that the majority of touch event handlers on the web never actually call preventDefault(), so browsers often block scrolling unnecessarily.

By marking a touch or wheel listener as passive, the developer is promising the handler won't call preventDefault to disable scrolling. This frees the browser up to respond to scrolling immediately without waiting for JavaScript, thus ensuring a reliably smooth scrolling experience for the user.

elem.addEventListener('touchstart', fn, { passive: true }); 

Keep your listeners fast

Modern browsers do not allow scroll events to be cancelled. For them, you will not see a performance gain when declaring scroll events as passive. To improve the scrolling behavior you should still try to keep the execution time of your handler to a minimum and combine it with a throttling Show archive.org snapshot mechanism.

Touch events can still be cancelled, mark them as passive whenever you can!

Browsers will make some listeners passive by default

From MDN Show archive.org snapshot :

The specification for addEventListener() defines the default value for the passive option as always being false. However, to realize the scroll performance benefits of passive listeners in legacy code, modern browsers have changed the default value of the passive option to true for the wheel, mousewheel, touchstart and touchmove events on the document-level nodes Window, Document, and Document.body. That prevents the event listener from canceling the event, so it can't block page rendering while the user is scrolling.

Compatibility with ancient browsers

IE11 and older browser versions Show archive.org snapshot do not support passive event listeners or even an object as the third argument to event listeners. If you need to support them, use the snippet below:

Because older browsers will interpret any object in the 3rd argument as a true value for the capture argument, it's important for developers to use feature detection or a polyfill when using this API, to avoid unforeseen results.

// Test via a getter in the options object to see if the passive property is accessed
var supportsPassive = false;
try {
  var opts = Object.defineProperty({}, 'passive', {
    get: function() {
      supportsPassive = true;
    }
  });
  window.addEventListener("testPassive", null, opts);
  window.removeEventListener("testPassive", null, opts);
} catch (e) {}

// Use our detect's results. passive applied if supported, capture will be false either way.
elem.addEventListener('touchstart', fn, supportsPassive ? { passive: true } : false); 
Profile picture of Michael Leimstädtner
Michael Leimstädtner
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Michael Leimstädtner to makandra dev (2020-10-22 11:04)