Throttling Scroll Events in JavaScript

Hero image for Throttling Scroll Events in JavaScript. Image by Jp Valery.
Hero image for 'Throttling Scroll Events in JavaScript.' Image by Jp Valery.

When you're working on a modern website or web application, you often tend to be working with a lot of moving parts. Things might need to animate on scroll, or you might need to detect when something is visible on screen and have it fade in (although using the Intersection Observer API would be far more performant for this). There are all kinds of reasons to attach a listener to the scroll event, but it can be a good idea to 'throttle' these functions.

One of the key reasons to throttle these functions (and listeners) is to avoid performance degradation; unlike some other events, onScroll tends to trigger very frequently which leads to lower performance, especially if you process a lot of data within that event, causing the interface to slow down or feel laggy. It also forces an increase in clientside resource use (i.e., the CPU and/or GPU), which can leave to even more lagging.

I'm sure you've arrived on websites in the past where your computer's fans whir into life as soon as things start to load. YouTube used to be extremely bad for this (although more due to general nonperformant code rather than scroll events in particular).

Another reason to throttle or regulate how often your functions run is a little less backend focused, but no less important. If you've got animations being triggered on scroll, you can run into a fair few weird visual glitches if you're running them without regulation. Things can look unfinished, broken, too quick, or just unpleasant if you don't slow them down long enough to seem intentional. You can avoid or at the very least mitigate these issues by preventing your functions from running, or your listeners from checking, every single millisecond. This is called 'throttling'. So, how do we throttle our scroll events?


Building a Diy Throttle Function

First things first, what do we need our throttling function to do?

To effectively throttle a function, we need to be able to check when it was previously run, then check that a certain amount of time (which we need to be able to have control over) has passed since that last run, and then run the function again if that amount of time has passed.

That all sounds relatively straightforward, so let's whip something up to handle this for us:

// Set up the throttler const throttle = (fn, delay) => {   // Capture the current time   let time = Date.now();    // Here's our logic   return () => {     if((time + delay - Date.now()) <= 0) {       // Run the function we've passed to our throttler,       // and reset the `time` variable (so we can check again).       fn();       time = Date.now();     }   } }  // Here's a dummy function that we want to throttle function runOnScroll(){   console.log('function fired!'); }  // We can use this like so (this will run runOnScroll at most once per second): window.addEventListener('scroll', throttle(runOnScroll, 1000));  

And that's it our DIY throttling function is done and without coincidence this is similar to how the Lodash throttle function works.

But what if you want to play it safe and use a library? There may be some edge cases that our function doesn't cover, so if you want to make sure you're not missing anything, it can be really handy to grab a specificallymade library to take care of this for you.


Using a Library

There are a couple of throttling libraries out there. I mentioned Lodash just above and personally I'd recommend it above other similar offerings. It's an excellent library when it comes to dealing with performance enhancements and is small enough not to bloat your code. Especially if you only import the parts you need, when you need them. It's opensource, wellvetted and tested, and easy to integrate into your projects.

Here's a brief example of how you could use the Lodash throttle function (after you've added it as a dependency or otherwise integrated it into your web app or site):

import { throttle } from 'lodash';const runOnScroll = () => {  console.log('function fired!');}window.addEventListener('scroll', throttle(runOnScroll, 250));

If you take a look at the throttle documentation, you'll see that all this is doing is saying: when the user is scrolling, trigger the 'runOnScroll' function at most once every 250 milliseconds.


The Wrap‑Up

Function throttling is important to avoid performance degradation, especially as designs get more and more complex, with ever more moving parts. There are plenty of ways to code a makeshift throttler yourself, but if you want something reliable and bulletproof, I would generally go with a purposemade library like Lodash, especially if you have a use for some of the other features the library offers too.


Categories:

  1. Development
  2. ES6
  3. Front‑End Development
  4. JavaScript