Read more

Passive event listeners may speed up your scroll and touch events

Michael Leimstädtner
October 22, 2020Software engineer at makandra GmbH

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.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

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!

On Chrome, touchstart and touchmove is passive by default

Because of the slow adoption of { passive: true } by web developers, Chrome 56+ has decided to make touchstart and touchmove events passive by default:

You still need to make your listeners passive for performance on browsers other than Chrome.

Compatibility with old 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); 
Posted by Michael Leimstädtner to makandra dev (2020-10-22 13:04)