Scroll-related animations have been used on the web for years. In recent years, they’ve started to become more common, perhaps in part due to devices being higher-performing and thus able to handle more animation.
There are a number of scroll related technologies out there, so this article’s aim is to provide an overview of them and tools to help choose the one that’s right for you. I’d argue that these technologies can be broken down into two broad categories: ones for specific scroll-related behaviors and ones for more generic scroll-related behaviors.
There are a few simple native CSS scroll effects that are supported by modern browsers. In some limited use cases they can be sufficient for your scroll animation needs.
If all you need is for an element to stay in the same place on scroll for a portion of the page, using
position: sticky is a good option. It’s straightforward and built into modern browsers. That said, a polyfill is required for IE support and some mobile browsers. For a solid overview, check out this article by Preethi.
This isn’t a technology as much as a technique, but it’s pretty handy for simple parallax effects where you want different pieces of the page to move at different speeds on scroll. There’s a good write up of the technique on Alligator.io and a bunch of examples on CodePen, like this Firewatch header. The biggest downside for me is that it’s difficult to understand what values to use to set the perspective and transforms in order to get the parallax effect exactly right.
Scroll snap points allow the browser to snap to particular scroll positions that you set after a user is done with their normal scrolling. This can be helpful for keeping certain elements in view. However, the API is still in flux so be careful to use the most up to date API and be careful about relying on it in production. This CSS-Tricks article by Max Kohler is a good place to learn about it right now.
Smooth scrolling is supported natively when jumping from section to section within a page using
Intersection observers are great if all you need for your animation is information related to whether or not and how much of an element is visible in the viewport. This makes them a good option for reveal animations. Even then, some things are difficult (though not impossible) using intersection observers, such as firing different animations depending on the direction an element enters the viewport. Intersection observers also aren’t very helpful if you want to do any scroll animations when an element is in between and not overlapping with the start and end points.
Using the scroll event will give you the most freedom in controlling animations on scroll. It allows you to affect an element on scroll no matter where it is in terms of the viewport and set up starting and ending points exactly as you need for your project.
With that being said, it can also be intense on performance if it isn’t throttled correctly and doesn’t have a convenient API to create particular behaviors. This is why it’s oftentimes helpful to use a good scrolling library that can handle the throttling for you and give you a more handy API to work with. Some can even handle a lot of the resizing issues for you!
There are a few holistic scrolling libraries that attempt to give you full control over animations on scroll without you having to perform all of the calculations yourself.
ScrollMagic provides a relatively simple API to create various effects on scroll and can be hooked into different animation libraries like GSAP and Velocity.js. However, it has become less maintained over the past few years, which lead to the creation of ScrollScene.
ScrollScene is essentially a wrapper to try and make ScrollMagic and/or the intersection observer more usable. It uses a custom, more maintained version of ScrollMagic and adds additional features like video playback, scene init breakpoints, and scene duration breakpoints. It also makes use of GSAP.
ScrollTrigger is an official GreenSock plugin for GSAP. It has a long list of features and has the most easy to use API of any scroll library (at least to me). Using it, you can have complete control to define where your scroll animations start and end, animate anything (WebGL, canvas, SVG, DOM, whatever) on scroll, pin elements in place while the animation is running, and more. Plus it has the support of GreenSock and the GreenSock forums.
While it doesn’t attempt to be as comprehensive of a scrolling library as the other libraries mentioned above, Locomotive Scroll is focused on providing custom smooth scrolling. You can also animate certain properties of DOM objects by adding data attributes or hook into the
onscroll event to animate other types of objects.
For some particular scroll animation effects, like sticky positioning and parallax, CSS technologies may be sufficient, at least when using a polyfill for browsers that don’t support those properties.
I generally recommend using GSAP’s ScrollTrigger because it can do everything that CSS properties can do, plus much more. ScrollTrigger will handle the browser support and calculations so that you can focus on animating!
Here’s a table covering which tools you can use to create particular effects:
|ScrollTrigger||Locomotive Scroll||ScrollScene||ScrollMagic||Intersection observers||Smooth Scrolling||CSS scroll snap points||CSS parallax||position: sticky|
|Scrubbing through animation with easing||✅||⚪️||⚪️||⚪️||⚪️||❌||❌||⚪️||❌|
|Snaps scroll position||✅||⚪️||⚪️||⚪️||⚪️||❌||✅||❌||❌|
|Dynamic Batching / Staggering||✅||❌||✅||❌||✅||❌||❌||❌||❌|
|Supports horizontal scroll effects||✅||✅||✅||✅||✅||✅||✅||✅||✅|
Here’s a table comparing various other aspects of scroll technology:
|ScrollTrigger||Locomotive Scroll||ScrollScene||ScrollMagic||Intersection observers||Smooth scrolling||CSS scroll snap points||CSS parallax||position: sticky|
|Usable in production (good browser support)||✅||⚪️||✅||✅||⚪️||⚪️||⚪️||✅||⚪️|
|Complete freedom in animation||✅||⚪️||✅||✅||❌||❌||❌||❌||❌|
|Works with DOM, Canvas, WebGl, SVG||✅||⚪️||✅||✅||✅||❌||❌||❌||❌|
|Works easily with resizing||✅||✅||✅||⚪️||✅||✅||✅||✅||✅|
|Restricts animation to relevant section||✅||❌||⚪️||⚪️||✅||✅||✅||❌||✅|
⚪️ = Partial support
❌ = No