A touchstart or wheel listener may call preventDefault, so the browser cannot start scrolling until the handler has run — which means every such listener delays scroll by the duration of its slowest execution.
// the browser must wait to find out whether you will cancel
el.addEventListener('touchstart', onTouch);
// a promise that you will not, so scrolling starts immediately
el.addEventListener('touchstart', onTouch, { passive: true });
// and the detection, because older browsers treat the object as truthy
let supported = false;
try {
window.addEventListener('t', null, { get passive() { supported = true; } });
} catch (e) {}
Chrome made touchstart and touchmove passive by default on the document in 2017, so the remaining wins are on specific elements and on wheel. Calling preventDefault inside a passive listener is ignored and logs a warning rather than throwing, which is a quiet way to break a carousel. The feature detection is ugly and necessary — a boolean third argument is the old signature and older browsers read the options object as true for capture.