I’ve been using web animations a lot recently, but haven’t managed to standardise how I use them in large projects. I feel it’s important to standardise the approaches and frameworks you use in a project in order to keep it maintainable and ease of comprehension high.

This is especially true with large projects maintained by multiple people where there may be many variants all achieving a similar outcome. Context switching can easily slow you down when you’re trying to focus on other aspects of your project like state management or business logic.

I’m a strong believer in ‘Separation of Concerns’ and feel like animations relate more to design than functionality, so I decided to evaluate moving all animation related Javascript to CSS in a project I’ve been working on. Here are some of the main ways of animating in web and some of the lessons I learned.

Javascript Animations

Here’s an example of how to use animations in Javascript with a popular animation library called Transit:

// Show
$element.transition({ opacity: 1.0, 500ms });
// Hide
$element.transition({ opacity: 0, 500ms });

CSS3 Transitions

And here’s how you can perform the equivalent animation with CSS3 transitions:

.my-element {
transition: opacity 500ms;
opacity: 0;
}
.my-element.show {
opacity: 1.0;
}
// Trigger the animation by adding the class with Javascript
$('.my-element').addClass('show');

CSS3 Transitions are great because they embody the concept of progressive enhancement (they gracefully degrade if the transition is not recognised, ie. browser compatibility), but there are other setbacks. The biggest one being ‘how do I get an element to transition immediately after some other transition?’

Sequencing and instantiation is a major problem when using CSS3 transitions. There are hacky workarounds, but ultimately it’s hard to make an element transition when it’s instantiated (what does it transition from?), and also when chaining multiple animations.

CSS3 Animations

One solution is to use the alternative ‘animation’ property, which supports sequencing animations via keyframes:

.my-element {
opacity: 0.0;
animation: fadeIn 500ms linear forwards;
}
@keyframes fadein {
to {
opacity: 1.0;
}
}

The important part here is the ‘forwards’ keyword which makes the element maintain the final state of the animation after it has finished.

The CSS3 animation property is great because the keyframing starts as soon as the element exists, solving the issue with animating on instantiation. It also solves the issue of sequencing animation, as keyframing supports multiple properties over time (not shown in the example above).

One setback is that they don’t support progressive enhancement — if the animation for some reason does not run correctly, then the element won’t end up in the expected state (I had this problem with flexbox width animations).

Looking back at JavaScript animations

I was at a conference last year where a speaker said ‘HTML is good for unary states (data), CSS is good for binary states (toggling), and JavaScript is good for multi states (interaction).’

Investigating CSS animations in depth definitely reinforced this for me, as it seems ideal for two simple states, but anything else is generally too complex.

Javascript animations are also arguably more expressive and easier to use, for example it’s common to have convenient access to common sequencing of animations like ‘shaking’ of an element. They are also improved constantly by the countless libraries and communities that make them more accessible and performant.

Conclusion

For now I’ve decided to use javascript animations with ‘Transit’, but I’m glad I spent some time investigating different options and becoming more confident in my decision.

I hope one day I can put animations in CSS where believe they belong. But at this point in time, I’ll reserve that for webpages with simple functionality such as static pages with little to transition.