Attaching JavaScript Handlers to Scroll Events — a how-NOT-to.

Don't do what I've seen countless devs do — attach JavaScript handlers to the window scroll event. There's a better way, here's Twitter's solution.
Published
Updated
Typical Read
2 minutes
Sponsored
Need help with website, a boost in ranking or online marketing? Contact me today for a free quote.
Find your next web developer job
jobs by Indeed

Attaching JavaScript Handlers to Scroll Events — a how-NOT-to. was originally published on Apr 26, 2017 and has recently been updated on Aug 6, 2020 to reflect emerging trends.

Boost page performance when attaching scroll events using the Twitter method — creating clean, reusable, performance-driven code.

I came across an article by John Resig, Learning from Twitter — it completely changed how I attach JavaScript handlers to scroll events. It’s a simple trick that sets a slight delay, will boost performance and help keep your code object-orientated. Here’s the correct way:

var scrolling = false;

$( window ).scroll( function() {
  scrolling = true;
});

setInterval( function() {
  if ( scrolling ) {
    scrolling = false;
    // Do your thang!
  }
}, 250 );

// or for modern browsers
document.addEventListener( 'wheel', ( evt ) => {
  // Do your thang!
}, { capture: false, passive: true });

The Wrong Way

It’s a very, very, bad idea to attach handlers to the window scroll event.

Depending upon the browser the scroll event can fire a lot and putting code in the scroll callback will slow down any attempts to scroll the page (not a good idea). Any performance degradation in the scroll handler(s) as a result will only compound the performance of scrolling overall.

$( window ).scroll( function() {
  // Do your thang!
});

The Correct Way

It’s much better to use some form of a timer to check every X milliseconds OR to attach a scroll event and only run your code after a delay (or even after a given number of executions – and then a delay).

var scrolling = false;

$( window ).scroll( function() {
  scrolling = true;
});

setInterval( function() {
  if ( scrolling ) {
    scrolling = false;
    // Do your thang!
  }
}, 250 );

The modern browser way.

For input events (touchstart, wheel, scroll, etc.), most modern browsers support passive events:

document.addEventListener(‘wheel’, (evt) => {
// … do stuff with evt
}, { capture: false, passive: true})

This allows the UI thread to immediately handle the scroll event before passing over control to your custom event handler. Without passive option, your custom handler will always be called before the UI thread does anything with the event.

Scroll event throttling (adding a delay between handling the events) can be implemented quite neatly using lodash or rxjs, if you have them in your build already.

Hope this helps to clear things up and provides some good advice for future infinitely-scrolling-page developers!

Did you find Attaching JavaScript Handlers to Scroll Events — a how-NOT-to. useful? Get articles in your inbox.

…and don’t worry, I hate spam as much as you. Expect to hear from me at most once a week.

Latest Job Postings
Posted on Aug 9, 2020 at 9:17pm
Full-time
Los Angeles
Posted on Aug 9, 2020 at 9:15pm
Full-time
Los Angeles
Posted on Aug 9, 2020 at 1:19am
Littleton, CO
jobs by Indeed
Sponsored
Sponsor my site by donating to help support open-source projects, like WordPress Zero Spam, Referrer Analytics & others.
Sponsored
Do you have a great article to share you want to contribute? Contact me about your idea.
Sponsored
Do you have a great article to share you want to contribute? Contact me about your idea.
Sponsored
Sponsor my site by donating to help support open-source projects, like WordPress Zero Spam, Referrer Analytics & others.
Sponsored
Help support open-source projects & pro-bono non-profit services by donating today.

4 Comments on “Attaching JavaScript Handlers to Scroll Events — a how-NOT-to.”

# Dec 3, 2019

Thank you! The John Resig article is also a nice dive into web history.

Michele

# Oct 24, 2019

Chrome is planning to treat such events as passive per default
https://www.chromestatus.com/feature/6662647093133312

Oliver Schöning

# Nov 4, 2018

Nice and simple 🙂 I occasionally also use _.debounce and _.throttle with lodash.

Brian

# May 11, 2018

For input events (touchstart, wheel, scroll etc) most modern browsers support ‘passive’ events e.g.

document.addEventListener(‘wheel’, (evt) => {
// … do stuff with evt
}, { capture: false, passive: true})

This allows the UI thread to immediately handle the scroll event before passing over control to your custom event handler. Without passive option, your custom handler will always be called before the UI thread does anything with the event.

Scroll event throttling (adding a delay between handling the events) can be implemented quite neatly using lodash or rxjs, if you have them in your build already

Leave a Reply

Your email address will not be published. Required fields are marked *

All comments posted on 'Attaching JavaScript Handlers to Scroll Events — a how-NOT-to.' are held for moderation and only published when on topic and not rude. Get a gold star if you actually read & follow these rules.

You may write comments in Markdown. This is the best way to post any code, inline like `<div>this</div>` or multiline blocks within triple backtick fences (```) with double new lines before and after.

Want to tell me something privately, like pointing out a typo or stuff like that? Contact Me.