Menu Search
Jump to the content X X
SmashingConf London Avatar

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf London, dedicated to all things web performance.

JavaScript Awesomeness — Or How To Animate Without jQuery

There’s a false belief in the web development community that CSS animation is the only performant way to animate on the web. This myth has coerced many developers to abandon JavaScript-based animation altogether, thereby (1) forcing themselves to manage complex UI interaction within style sheets, (2) locking themselves out of supporting Internet Explorer 8 and 9, and (3) forgoing the beautiful motion design physics that are possible only with JavaScript.

Reality check: JavaScript-based animation is often as fast as CSS-based animation — sometimes even faster. CSS animation only appears to have a leg up because it’s typically compared to jQuery’s $.animate(), which is, in fact, very slow. However, JavaScript animation libraries that bypass jQuery deliver incredible performance by avoiding DOM manipulation as much as possible. These libraries can be up to 20 times faster than jQuery.

Further Reading on SmashingMag: Link

So, let’s smash some myths, dive into some real-world animation examples and improve our design skills in the process. If you love designing practical UI animations for your projects, this article is for you.

Why JavaScript? Link

CSS animations are convenient when you need to sprinkle property transitions into your style sheets. Plus, they deliver fantastic performance out of the box — without your having to add libraries to the page. However, when you use CSS transitions to power rich motion design (the kind you see in the latest versions of iOS and Android), they become too difficult to manage or their features simply fall short.

Ultimately, CSS animations limit you to what the specification provides. In JavaScript, by the very nature of any programming language, you have an infinite amount of logical control. JavaScript animation engines leverage this fact to provide novel features that let you pull off some very useful tricks:

Note: If you’re interested in learning more about performance, you can read Julian Shapiro’s “CSS vs. JS Animation: Which Is Faster?9” and Jack Doyle’s “Myth Busting: CSS Animations vs. JavaScript10.” For performance demos, refer to the performance pane11 in Velocity’s documentation and GSAP’s “Library Speed Comparison12” demo.

Velocity and GSAP Link

The two most popular JavaScript animation libraries are Velocity.js13 and GSAP14. They both work with and without jQuery. When these libraries are used alongside jQuery, there is no performance degradation because they completely bypass jQuery’s animation stack.

If jQuery is present on your page, you can use Velocity and GSAP just like you would jQuery’s $.animate(). For example, $element.animate({ opacity: 0.5 }); simply becomes $element.velocity({ opacity: 0.5 }).

These two libraries also work when jQuery is not present on the page. This means that instead of chaining an animation call onto a jQuery element object — as just shown — you would pass the target element(s) to the animation call:

/* Working without jQuery */

Velocity(element, { opacity: 0.5 }, 1000); // Velocity, 1, { opacity: 0.5 }); // GSAP

As shown, Velocity retains the same syntax as jQuery’s $.animate(), even when it’s used without jQuery; just shift all arguments rightward by one position to make room for passing in the targeted elements in the first position.

GSAP, in contrast, uses an object-oriented API design, as well as convenient static methods. So, you can get full control over animations.

In both cases, you’re no longer animating a jQuery element object, but rather a raw DOM node. As a reminder, you access raw DOM nodes by using document.getElementByID, document.getElementsByTagName, document.getElementsByClassName or document.querySelectorAll (which works similarly to jQuery’s selector engine). We’ll briefly work with these functions in the next section.

Working Without jQuery Link

(Note: If you need a basic primer on working with jQuery’s $.animate(), refer to the first few panes in Velocity’s documentation.15)

Let’s explore querySelectorAll further because it will likely be your weapon of choice when selecting elements without jQuery:

document.querySelectorAll("body"); // Get the body element
document.querySelectorAll(".squares"); // Get all elements with the "square" class
document.querySelectorAll("div"); // Get all divs
document.querySelectorAll("#main"); // Get the element with an id of "main"
document.querySelectorAll("#main div"); // Get the divs contained by "main"

As shown, you simply pass querySelectorAll a CSS selector (the same selectors you would use in your style sheets), and it will return all matched elements in an array. Hence, you can do this:

/* Get all div elements. */
var divs = document.querySelectorAll("div");

/* Animate all divs at once. */
Velocity(divs, { opacity: 0.5 }, 1000); // Velocity, 1, { opacity: 0.5 }); // GSAP

Because we’re no longer attaching animations to jQuery element objects, you may be wondering how we can chain animations back to back, like this:

$element // jQuery element object
	.velocity({ opacity: 0.5 }, 1000)
	.velocity({ opacity: 1 }, 1000);

In Velocity, you simply call animations one after another:

/* These animations automatically chain onto one another. */
Velocity(element, { opacity: 0.5 }, 1000);
Velocity(element, { opacity: 1 }, 1000);

Animating this way has no performance drawback (as long as you cache the element being animated to a variable, instead of repeatedly doing querySelectorAll lookups for the same element).

(Tip: With Velocity’s UI pack, you can create your own multi-call animations and give them custom names that you can later reference as Velocity’s first argument. See Velocity’s UI Pack documentation16 for more information.)

This one-Velocity-call-at-a-time process has a huge benefit: If you’re using promises17 with your Velocity animations, then each Velocity call will return an actionable promise object. You can learn more about working with promises in Jake Archibald’s article18. They’re incredibly powerful.

In the case of GSAP, its expressive object-oriented API allows you to place your animations in a timeline, giving you control over scheduling and synchronization. You’re not limited to one-after-the-other chained animations; you can nest timelines, make animations overlap, etc:

var tl = new TimelineMax();
/* GSAP tweens chain by default, but you can specify exact insertion points in the timeline, including relative offsets. */
  .to(element, 1, { opacity: 0.5 })
  .to(element, 1, { opacity: 1 });

JavaScript Awesomeness: Workflow Link

Animation is inherently an experimental process in which you need to play with timing and easings to get exactly the feel that your app needs. Of course, even once you think a design is perfect, a client will often request non-trivial changes. In these situations, a manageable workflow becomes critical.

While CSS transitions are impressively easy to sprinkle into a project for effects such as hovers, they become unmanageable when you attempt to sequence even moderately complex animations. That’s why CSS provides keyframe animations, which allow you to group animation logic into sections.

However, a core deficiency of the keyframes API is that you must define sections in percentages, which is unintuitive. For example:

@keyframes myAnimation {
   0% {
      opacity: 0;
      transform: scale(0, 0);
   25% {
      opacity: 1;
      transform: scale(1, 1);
   50% {
      transform: translate(100px, 0);
   100% {
      transform: translate(100px, 100px);

#box {
   animation: myAnimation 2.75s;

What happens if the client asks you to make the translateX animation 1 second longer? Yikes. That requires redoing the math and changing all (or most) of the percentages.

Velocity has its UI pack19 to deal with multi-animation complexity, and GSAP offers nestable timelines20. These features allow for entirely new workflow possibilities.

But let’s stop preaching about workflow and actually dive into fun animation examples.

JavaScript Awesomeness: Physics

Many powerful effects are achievable exclusively via JavaScript. Let’s examine a few, starting with physics-based animation.

The utility of physics in motion design hits upon the core principle of what makes for a great UX: interfaces that flow naturally from the user’s input — in other words, interfaces that adhere to how motion works in the real world.

GSAP offers physics plugins that adapt to the constraints of your UI. For example, the ThrowPropsPlugin tracks the dynamic velocity of a user’s finger or mouse, and when the user releases, ThrowPropsPlugin matches that corresponding velocity to naturally glide the element to a stop. The resulting animation is a standard tween that can be time-manipulated (paused, reversed, etc.):

See the Pen Draggable (Mini)21 by GreenSock (@GreenSock3522) on CodePen3633292623.

Velocity offers an easing type based on spring physics. Typically with easing options, you pass in a named easing type; for example, ease, ease-in-out or easeInOutSine. With spring physics, you pass a two-item array consisting of tension and friction values (in brackets below):

Velocity(element, { left: 500 }, [ 500, 20 ]); // 500 tension, 20 friction

A higher tension (a default of 500) increases the total speed and bounciness. A lower friction (a default of 20) increases ending vibration speed. By tweaking these values, you can separately fine-tune your animations to have different personalities. Try it out:

See the Pen Velocity.js – Easing: Spring Physics (Tester)24 by Julian Shapiro (@julianshapiro322825) on CodePen3633292623.

JavaScript Awesomeness: Scrolling Link

In Velocity, you can enable the user to scroll the browser to the edge of any element by passing in scroll as Velocity’s first argument (instead of a properties map). The scroll command behaves identically to a standard Velocity call; it can take options and can be queued.

Velocity(element, "scroll", { duration: 1000 };

See the Pen Velocity.js – Command: Scroll w/ Container Option27 by Julian Shapiro (@julianshapiro322825) on CodePen3633292623.

You can also scroll elements within containers, and you can scroll horizontally. See Velocity’s scroll documentation30 for further information.

GSAP has ScrollToPlugin, which offers similar functionality and can automatically relinquish control when the user interacts with the scroll bar.

JavaScript Awesomeness: Reverse Link

Both Velocity and GSAP have reverse commands that enable you to animate an element back to the values prior to its last animation.

In Velocity, pass in reverse as Velocity’s first argument:

// Reverse defaults to the last call's options, which you can extend
Velocity(element, "reverse", { duration: 500 });

Click on the “JS” tab to see the code that powers this demo:

See the Pen Velocity.js – Command: Reverse31 by Julian Shapiro (@julianshapiro322825) on CodePen3633292623.

In GSAP, you can retain a reference to the animation object, then invoke its reverse() method at any time:

var tween =, 1, {opacity:0.5});

Transform Control Link

With CSS animation, all transform components — scale, translation, rotation and skew — are contained in a single CSS property and, consequently, cannot be animated independently using different durations, easings and start times.

For rich motion design, however, independent control is imperative. Let’s look at the dynamic transform control that’s achievable only in JavaScript. Click the buttons at any point during the animation:

See the Pen Independent Transforms34 by GreenSock (@GreenSock3522) on CodePen3633292623.

Both Velocity and GSAP allow you to individually animate transform components:

// Velocity
/* First animation */
Velocity(element, { translateX: 500 }, 1000);
/* Trigger a second (concurrent) animation after 500 ms */
Velocity(element, { rotateZ: 45 }, { delay: 500, duration: 2000, queue: false });

/* First animation */, 1, { x: 500 });
/* Trigger a second (concurrent) animation after 500 ms */, 2, { rotation: 45, delay: 0.5 });

Wrapping Up Link

  • Compared to CSS animation, JavaScript animation has better browser support and typically more features, and it provides a more manageable workflow for animation sequences.
  • Animating in JavaScript doesn’t entail sacrificing speed (or hardware acceleration). Both Velocity and GSAP deliver blistering speed and hardware acceleration under the hood. No more messing around with null-transform hacks.
  • You don’t need to use jQuery to take advantage of dedicated JavaScript animation libraries. However, if you do, you will not lose out on performance.

Final Note Link

Refer to Velocity37 and GSAP’s documentation to master JavaScript animation.

(al, il)

Front page image credits: NASA Goddard Space Flight Center 38.

Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38

↑ Back to top Tweet itShare on Facebook

Julian Shapiro is a startup founder and a developer. His first startup, NameLayer, was acquired by Techstars. His current focus is advancing motion design on the web. Follow him for tweets on UI animation: @Shapiro.

  1. 1

    CSS-based animations that only trigger compositing can typically proceed without main thread intervention so should you get a GC pause or some other main thread halt, the CSS-based animation can continue. This is where the “myth” has originated and that assertion is not incorrect (and hence not a myth), but it is an incomplete picture.

    What matters is _what exactly_ you animate with either JS or CSS, as that will govern your performance characteristics. If your animation changes a property that triggers layout or paint (which many do: it will be difficult to achieve 60fps, particularly on mobile. My hope is that in the future that’s not the case, but today that’s true.

    In any case it’s nice to see pretty animations delivered through Velocity or GSAP. I still get frustrated that jQuery animates without requestAnimationFrame, but I guess that’s a topic for another day! :)

  2. 2

    I’ll give it a try, good article :)

  3. 3

    Nice comparison and examples.

    I’m using GSAP’s TweenMax for most projects already mainly because of IE8 support. This goes for complex animations as well as necessary animations. If we’re talking about simple fade-in effects or small (but beautiful) transitions, I always use CSS only.

    I never tried velocity.js but I’ve read quite a few good things about it. I don’t see a need to try it / switch right now though.

    I’d love to see a detailed article about GSAP’s TimelineMax library.

  4. 4

    I’ve done my share of animations with GSAP and I have to admit I love it. Lewis above is correct to a point, yet when I’m writing my animations, I have to ask myself whether it’s prudent to have them split in two, some in css and some in js. On top of that, the company I work for is a major ebay seller and ebay isnt exactly friendly when it comes to js libraries. That means we’re forced to load at least the very basic (common) animations from our library with css, whether we like it or not.

    • 5

      Oh no you’re absolutely right, I’m not actually voting in one direction or another. I generally think declarative animations are best, but I also think if you’ve started down the JS animation path for whatever reason then your sanity is probably best served by sticking with it entirely! Mix ‘n’ match can get very hairy.

  5. 6

    This is an awesome article. These libraries really have the ability to bootstrap meaningful interactions.

  6. 7

    Dmitri Tcherbadji

    September 5, 2014 3:47 am

    Great article and a reminder (as many have already pointed out above) that “it all depends”.

    Personally I try to stray away from using too many libraries and plug-ins as much as possible. It helps to free up some resources for the user and avoid managing too many assets that might be changed or updated elsewhere. But if the project requires advanced animation, CSS is definitely not the best way – it simply isn’t made for complex, combined movements or physics-involved motions shown above. It would make the most sense to use either of these libraries and enjoy a breeze of fast, easy coding resulting in beautiful motion.

    Most of my projects involve very straight-forward interactions however, where animation is more of a “helper” that guides the user a little better than a static element. In this case I think it’s best to just use CSS3 transitions since objective is usually simple enough as “move A to B”. Some browsers will not gel well with it of course, like IE8. But neither will they render my rounded borders – and I really do not intend to use another plugin just to make that happen.

    Making things work on really really old, crappy browsers just like they do in a new Chrome release is extremely counter-productive. Things should work there of course – if the data shows that the users demand that. But they do not have to be animated, they do not have to be very pretty. Because adding weight to the project in order to do fancy things will punish me, punish the “modern” users and will punish the older browsers’ users. Advanced graphics will slow down their dusty boxes (besides, anyone who uses IE8 by now is probably used to ugly web already).

    • 8

      I guess you have the luxury of not supporting outdated browsers like IE <9.

      Most of us have to support legacy browsers, that's why libs like jQuery were built in the first place.

  7. 9

    Otto Nascarella

    September 5, 2014 4:40 pm

    Nice work with Velocity!

    What about callbacks with this new syntax?

    • 10

      Julian Shapiro

      September 5, 2014 6:27 pm


      Same as always; pass in a `complete` or `begin` callback. Check the docs for both libs — very straight-forward.

  8. 11

    Nice! Been just digging into this topic last week – because I prefer Vanilla Javascript over excessive framework / library bloat. Also, you so readily forget about how to actually get things done in Javascript, while always having to goof around with jQuery all day.

    cu, w0lf.

  9. 12

    This is very Nice Articles. The Examples for velocity has been impressed. :)

  10. 13

    I haved used GSAP since its beta period and I must admit I cannot change it with anything. I has allowed me to produce extremely complex animations with great performance and in a just a few lines of code. JS animating is more close to me because I come from a strictly code based background and it feels more natural to declare things in an object oriented way. However I have witnessed some extremely well done animations that were made via CSS.
    It is only beneficial to all to have more options. Also well done on the article it was an easy read.

  11. 14

    It’s worth noting that document.querySelectorAll does not return an array. It returns a non-live NodeList

  12. 15

    Daniel Schwarz

    September 9, 2014 3:33 pm

    Nice article. I’ve always been familiar with transit.js, and still don’t have a reason to switch as I’m very happy with it and use it for a lot of websites, being one of them.

    It’s lightweight and useful for chaining animations, but if it’s something simple, CSS is always the method I would use, especially if you can take the time to create your own animation mixins for LESS (only compile what you need).

  13. 16

    There are far more advanced js libs:

  14. 18

    La Casita Del Cuco

    September 13, 2014 8:01 am

    But Jquery animation do not work on mobiles! Or is that a myth as well? With growing mobile use an important point to take in consideration.

  15. 19

    Great Post. Thanks

  16. 20

    Good comparisons.

  17. 21

    Very simple compare between jQuery (or native js) and GSAP:

    GSAP is able to animate to an other position while it’s changing its background color at the same time. During a tween of GSAP you can call a function to handle some data, so you can build-in a tracker. Plus during the animation you can pause and resume it or increasing/decreasing time.

    jQuery is unable to do anything like that, and ofcourse.. tweening (‘inbetweening’) looks 10 times better than normal position change (jQuery animate, or own javascript loop).

    Velocity is also outdated agains GSAP.

  18. 22

    Very informative article, tough choice between the two. I like them both, I wish that Velocity had better docs and examples. Greensock wins out in the learning resource department

  19. 23

    Great article, tx!

    Stumble upon while i was looking for a tutorial, some inspiration to make something like for a quiz. Where the page transistion happens when you answer a question.

    Any ideas, tips where i can find some inspiration/tutorials?


  20. 24

    Good Article, But CSS3 object-fit property is good for animation

  21. 25

    Does any of these libraries provide a way to animate non-css properties like ‘s rows and cols attributes?


↑ Back to top