In both of those posts, we built up our animations by hand. However, as your project grows or your designs become more complicated, implementing motion manually can become challenging and difficult to maintain. This brings us to our final topic of this series: animation libraries.
To library, or not to library?
In web development, a library is a collection of code that can be imported into a codebase to add or streamline functionality. Some libraries can be found across most websites and applications, such as Moment (which simplifies working with dates in Javascript) or Lodash (a utility library described as the “missing functionality of Javascript”).
There are also multiple libraries that do roughly the same thing, and the choice between each library depends on the minutiae of the developer’s needs and their own personal preference. Swiper.js, Slick.js, and Splide.js are just three of the many, many libraries created solely to streamline building sliders and carousels.
When it comes to adding motion to your site, how do you decide which path to take?
There are plenty of valid reasons to build your own implementation rather than reach for a library:
The best way to learn is by doing. Building up animations yourself means you know what goes into it and how it works. If you choose to move towards a library later, you’ll understand what’s going on behind the scenes. Animation in particular involves an artistic combination of CSS and JS, and it’s a skill important for every front-end developer to maintain.
It does just what you need it to do. Libraries are built to handle many different use cases and scenarios and often come with more tools than you need. By building your own custom implementation, you can simplify the script to create a precise result. No unnecessary configuration options, no removing or overwriting default behavior – it works like you want it to work, the way you want it to work.
No learning curve. Scouring documentation to learn a new library can be tedious and time-consuming. Building your own implementation means that you don’t need to teach yourself the “[enter library name here] way” to do something. Instead, you can just apply the vanilla Javascript and CSS skills you already have and spend time planning out the actual implementation process.
Performance. Libraries often come with more tools than you need which can add unnecessary bloat to your project. Writing your own code is helpful in reducing that bloat and only providing the tools you need.
Writing code by hand is a great way to learn or reinforce the fundamentals, and to ensure that your application does exactly what you want it to do.
On the other hand, there are plenty of great reasons to reach for a library instead:
Avoid reinventing the wheel. Libraries exist for a reason – although you can see some hilarious exceptions here. They solve a problem that is either difficult or time-consuming. For example, instead of spending days building a specific slider, you can install a library, configure it to spec, and style it accordingly in a matter of hours. Libraries first and foremost, when selected well, save time.
Less hidden issues or bugs. Libraries also help you avoid pitfalls that other developers have already discovered and solved. These can be accessibility concerns, edge cases, browser compatibility, and more. Using a library can cut down on your own bugs and issues during QA because the library authors (or in the case of open source libraries, the community who uses them) have already found and patched them for you.
Upkeep and maintenance. The benefit of a well-documented library is that the documentation is already written for the other developers on your team who may need to make changes to your work during the development period or subsequent maintenance work.
Performance. Yes, I know we mention performance as a benefit to coding your own features, but in today’s age of Core Web Vitals and page speed tests, performance considerations have moved to the forefront of web development and therefore library development. If you choose your libraries wisely, library authors will have addressed these issues as well or at least given tips in their documentation on how you can implement features with performance in mind.
Let’s take a look at some examples from Imarc
Magnitude - Process Runner
The animation above includes multiple moving parts that can be triggered by scroll, user interaction, their own sequencing in the timeline, or playing off of the choreography of other elements. Building something like this without the support of a library would be somewhat of a headache and difficult to debug, update, or refactor.
Blue Voyant - Homepage
On the other hand, a simple fly-up animation like the one above can be done with a quick Intersection Observer instance and some CSS. For small effects like this, building it manually may be the better, more performant, and more maintainable choice.
Questions to consider
Choosing whether or not to use a library should be carefully considered with your team. Here are three questions to consider:
What’s the easiest way I can achieve what I’m after? Consider if CSS or a bit of vanilla javascript is enough.
Does the element I’m adding motion to affect any other elements? The more elements in play, the more complicated the logic of motion becomes.
How many different trigger points should the motion have? A trigger point is any method that manipulates the motion. There are user trigger points (click, hover/focus, drag, swipe, scroll) as well as sequenced trigger points (delay, timing, play/pause/stop control, direction, stagger). A combination of user and sequenced trigger points can create some very complex choreography – this is when a library can be extremely helpful.
The best animation libraries
Once we’ve made the decision to use a library, we have to find the right library for the job.
Here are some of our favorites:
Anime.js is a powerful and lightweight javascript library with lots of great options for timing and sequencing which can run complicated timelines at 60fps.
GSAP / Greensock has long been the go-to library for modern web animation, especially for more complicated sequencing. It has a robust feature list as well as a set of premium plugins that are the gold standard for creating animation with SVGs.
Framer Motion is an incredible React motion library with a wonderful collection of motion components and a simple declarative syntax.
@vueuse/motion is another declarative library for Vue 2 & 3 built from Popmotion which was one of the original Vue animation libraries.
MotionOne is an exciting new library from the creator behind Framer Motion, built on top of the Web Animations API with huge performance features. It also has a built-in Vue 3 declarative version of its library as well as an incredible Dev Tools chrome extension.
Using the Anime.js animation library
For the following examples we will use Anime.js. It has some of the best documentation out there, and the learning curve is minimal given that much of the syntax is the same you would use in CSS.
Example #1: Card Group Toggle with <transition-group> and Anime.js
In our first article we learned about Vue’s native transition and transition-group components to create easy CSS transitions for our elements as they entered and exited the DOM. Below we take that same concept but use Anime.js to create our transitions instead of CSS:
The first thing you’ll notice is instead of naming the transition-group, we’ve added the :css=”false” attribute and we’re instead using the components built-in transition events to attach javascript methods. By telling the component not to use CSS, it keeps those transitions from being built and potentially conflicting with our javascript. We’ve also added a data-index attribute that we use later to create our stagger for the cards.
When using JS-only transitions in the transition or transition-group components, it's important to run the provided DONE method once the transition is complete. This tells the browser the animation is complete. Without it, the hooks would be called synchronously and the transitions would finish immediately.
As you can see, with just a few lines of code we can create different entrance and exit transitions – the Anime.js syntax closely mimics the way we assign properties in CSS but can also receive an array as the value. This lets us define the first and last frame of the animation with ease.
Example #2: Vue 3 Motion: onIntersect composable + Anime.js
In our second article, we worked with Vue 3 and created an onIntersect composable which changed CSS Variable values once the element was scrolled into view. In our example below, we’ve built a component with that same composable and Anime.js that runs a transition when the box is in view. We’re able to assign different transitions to each instance of the component through a prop using a series of prebuilt transitions objects (see the ‘/utilities/transitions.js’ folder) that we spread into the anime object on mount.
We build the anime instance once the component is mounted so that it puts the component in its pre-transition setup off-screen. If we tried to create the instance inside the onEnter method, we’re likely to see the element flash as it intersects and then tries to add the anime instance.
By default, Anime.js will run the transition as soon as the instance is built, so we have to make sure that autoplay is false. We can then use our onEnter and onExit methods to control the transition.
const onEnter = () => {
if (hasEnteredOnce) {
// clean up from the exit transition
_.motion.pause(); // if the exit transition is currently running, pause it.
_.motion.reverse(); // change the direction back to the original
}
_.motion.play(); // run the transition
if (!hasEnteredOnce) {
// allow exit transitions to run.
hasEnteredOnce = true;
}
};
const onExit = () => {
// keeps exit transition from running before the first entrance.
if (hasEnteredOnce) {
_.motion.pause(); // if the enter transition is currently running, pause it.
_.motion.reverse(); // change the direction of the transition
_.motion.play(); // run the new reversed transition.
}
};
javascript
Anime.js has some wonderful built-in timeline controls that allow us to run ‘play’, ‘pause’, ‘seek’, ‘reverse’, and ‘reset’ from outside of the initial anime instance. Using these, we’re able to create some safety nets and clean-up steps if one transition tries to run in the middle of another.
Implementing animation
Like everything with web development, animation and motion are fast-moving areas with ever-changing and ever-improving tools. Don’t be afraid to push the boundaries of what you think motion can do on the web. Poke around the internet, get inspired by the work of other developers and designers, and find your own styles of motion for your projects. Don’t forget to contextualize and make sure that the animations are not causing undue issues for the users of your site, but rather make it an experience they will remember and enjoy.
Most importantly – have some fun with it!
This is the final post in this series, but keep checking back to learn more about different front-end technologies. As always, if you have any project or animation needs, let’s talk!