About passive event listeners

3 min readJun 17, 2016

I have been hearing about it for a couple of months but now is has been shipped on Chrome 51 and Firefox Nightly, EventListenerOptions are here.

Today I just want to share my thoughts about this new feature and why I’m sure is going to be game changer when talking about web performance, briefly, it allows to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners.


When talking about performance, scrolling is a key aspect of your application, this means that as soon as the users perceives a non-smoth scroll on your page he will quickly know that something goes wrong.

It’s well known that doing expensive operations (manipulating the DOM, processing multiple xhr, CPU intense operations, etc…) while the user performs a scroll is an anti-pattern when building web apps, but what is not that well known for quite a lot of front-end developers is that even if you don’t do any of the stuff listed above but you just have touch handlers added to your page, you potentially will pay a huge price for it, even if you do nothing in those handler.

This issue happen because when you start performing a scroll, at that point, the browser doesn’t know if you are going to call preventDefault in you handler which will prevent the browser to do the normal scroll on the page. This means the browser will wait until check if preventDefault has been called and later update the scroll position, the sad thing about this is that 90% of the times you will not call it since you want the browser to do the scroll, but just because you have those handlers you will lose that default smoothness.

Introducing { passive: true }

Now, thanks to EventListenerOptions you have the ability to tell the browser that you just want to do your stuff and you are not gonna call preventDefault.

document.addEventListener('touchstart', handler, {passive: true});

That simply addition will help you to prevent scroll junk on your sites, specially on mobile.


As you can see, the new addEventListener introduces a breaking change since before it was expecting a boolean useCapture as third argument, which now turns into an object, luckily there’s already a polyfill for it which is backwards compatible, so if you pass this:

document.addEventListener('touchstart', handler, true);

it will be translated to:

document.addEventListener('touchstart', handler, {capture: true});

Making passive default

One thing that I was not happy about it was the fact of having to upgrade tons of addEventListener declarations from my already existing applications in order to take benefit of the new api “for free”, so, I came up with:

Why just don’t make them passive by default whenever is possible?

Done, I created default-passive-events - github.com/zzarcon/default-passive-events, a 40 lines snippet written in old school javascript that would make every single event listener of your app {passive: true}.

It actually turns out that I just had to modify less than 20 event listener across all my apps and add there the {passive: false}… that might look a lot but, if you think about the number of event listeners that I would had to upgrade using the other way it became something ridiculous.


Finally I will just say that you really have to try it out in your current apps, since the changes required are really small, and check if actually performs better or not. I also have to say thanks to Rick Byers which has been working on the feature since the beginning and wrote this awesome post some years ago.

You can follow me on Twitter or Github @zzarcon




A bunch of colleagues writing about #swift #javascript #ruby #algorithms #performance and coding stories