Scrolling on the web: A primer

In notebook:
Article Notes
Created at:
Performance JavaScript DOM jQuery libraries types of scrolling, not all behave the same
  • User scrolls with two fingers on a touch pad
  • User scrolls with one finger on a touch screen
  • User scrolls with a mouse wheel on a physical mouse
  • User clicks the sidebar and drags it up and down
  • User presses up, down, PageUp, PageDown, or spacebar keys on a keyboard

Browsers are single threaded so scrolling has to wait for all other (JavaScript) operations to finish which can degrade scrolling smoothness. 

Nowadays, every major browser engine (Blink, EdgeHTML, Gecko, WebKit) supports off-main-thread scrolling to one degree or another (with Firefox being the most recent member of the club, as of Firefox 46)

This means that scrolling is on a separate thread from the main JavaScript (except for keyboard input driven scrolling).

How event listeners interfere with scrolling

If you add an event listener to the ​window​ or ​document​ then scrolling again has to wait for the main JavaScript thread to finish since it can contain an ​event.preventDefault()​ anywhere in the code. 
So scrolling again becomes janky. 
Passive event listeners
You declare your event listener to be passive ie. it will never call ​event.preventDefault()​. Worsk in Chrome, Firefox and Safari and the latest version of Edge (April 2017). This the default in Chrome 56.
Local event listeners
If you attach the event listener other than ​window​ or ​document​ then it will not block scrolling of the window. But this listens for the scrolling of the individual DOM element not the page...
.addEventListener(“wheel”, function (e) {
  // In theory, I can only block scrolling on the div itself!


First off, it’s best to avoid attaching wheel or touch listeners to the global document or window objects, and instead add them to smaller scrollable elements. Developers should also use passive event listeners whenever possible, with feature detection to avoid compatibility issues. Using Pointer Events (there is a polyfill) and “scroll” listeners are also surefire ways to prevent unintentional scroll-blocking.