By the term “animation” we most often mean animated films - the “cartoons” we have loved since childhood. But if we look at the explanatory dictionary, we find out that translated from French it means “revival”, “animation”. And here it turns out that this meaning surprisingly accurately fits not only the film industry, but also web technologies.

The use of various animation effects (transitions, movements, transformations, etc.) significantly “enlivens” the website, allows you to control the user’s attention, switching it to the required element and giving certain visual cues.

Speaking about animation, one cannot fail to mention the well-known 12 principles formulated by the animators of the Disney studio, the use of which is extremely important for the reasonable and high-quality use of animation effects.

Speaking about technologies that enable the use of animation in web pages, we can highlight several, but perhaps none of them are as powerful as . Just a few years ago, Flash animation technology was a formidable competitor and very popular. But now it seems that she best years behind and it is gradually being replaced from website pages by more powerful and flexible Java scripts. And if you decide to seriously use animation on your website, then you should rely on JavaScript. And in order to make a smart choice of library, I made today’s review.

Dynamics.jsI'll start with Dynamics.js. This is a serious and powerful library that allows you to create physically realistic animation (such as harmonic damped oscillations of a point on home page site). The library is capable of managing the properties of any DOM element. Dynamics.js is used to create menus, buttons, process indicators, markers. In this case, a wide variety of parameters are available, such as frequency, damping decrement, parameters characterizing elasticity or process duration, etc.

Cta.jsThe small cta.js library is designed for creating animation effects of the “action-effect” type on the page, i.e. hovering or clicking the mouse pointer over an object produces a specific effect. It is very convenient to use when developing tiled interfaces, when clicking on an element leads to its opening as a modal window, on the entire page, or as a side slide panel.

Beep.jsAn interesting library that uses the WebAudio API to create a music synthesizer on a page. Can be used in developing an online music textbook or as a fun toy.

Rainyday.jsIncredibly beautiful rain effect with drops of different sizes flowing down. However, in my opinion, large drops lack realism (maybe the same physics that is present in Dynamics.js?). However, the existing API allows you to create your own objects and control their behavior, creating even more incredible effects.

Dom-Animator.jsDom-Animator.js is a so-called “easter egg”. The effect it produces is not visible to the “naked” eye, i.e. for those who view the page in a regular browser window. But those who parse your code will see it in the console (if you still don’t understand what we’re talking about, there’s a video here that will make everything clear).

FamousFamous is an event-driven JS library for creating modern animation. It has a powerful geometric core that allows you to manipulate various 3D objects - point and volumetric - apply forces and accelerations to them, impose restrictions and control collisions.

Bounce.js A good JavaScript library for creating impressive animations using CSS. Allows you to apply various types of movement, rotation, scaling and transformation to objects.

Snabbt.js A lightweight and fast library that, according to the developers, produces 60 fps even on mobile devices. Using transformation matrices, CSS allows you to move, rotate, scale and perform other manipulations with objects. It also allows you to apply special effects to objects that attract attention, which can be used when filling out forms.

RekapiRekapi allows you to use both CSS keyframe animation (@keyframes rule) and DOM animation using JavaScript. This library allows you to create quite complex dynamic objects, such as pie and line charts, timelines and other user interface elements.

ShiftyShifty is a library containing everything necessary for full-fledged keyframe animation (the so-called “twinning”), and the number of objects can be simply huge. It is a low-level library that can be used as a core for higher-level platforms or libraries. Actually, Shifty is used as the core of the aforementioned Rekapi.

You can use JavaScript to create complex animations, but are not limited to the following elements:

  • Fireworks
  • Blackout effect
  • Collapse or unfold.
  • Go to or leave a page
  • Object Movements

You might be interested in an existing JavaScript-based animation library: Script.Aculo.us.

This article provides a basic understanding of how to use JavaScript to create animations.

JavaScript can be used to move multiple DOM elements ( , or any other HTML element) on pages according to some pattern defined by a logical equation or function.

JavaScript provides the following two functions that are often used in animation programs.

  • setTimeout(function, duration) – this function calls function after duration milliseconds from the moment it was called.
  • setInterval(function, duration) – this function calls function after every duration millisecond.
  • clearTimeout(setTimeout_variable) – This function causes any timer set by the setTimeout() functions to be cleared.

JavaScript can also set several attributes of an object, including its position on the screen. You can set the attribute top and left of the object to place it anywhere on the screen. Here is its syntax.

// Set the distance from the left edge of the screen. object.style.left = distance in pixels or points; or // A specified distance from the top edge of the screen. object.style.top = distance in pixels or points;

Hand animation

So let's implement one simple animation using DOM object properties and JavaScript functions as follows. The following list contains various methods DOM.

  • We use JavaScript function getElementById() to get the DOM object and then assign it to the global variable imgObj .
  • We initialized the init() function to initialize the imgObj, where we set its position and left attributes.
  • We call the initialization function when the window is loaded.
  • Finally, we call the moveRight() function to increase the left distance by 10 pixels. You can also set it to a negative value to move it to the left.
Example

Try the following example.

Animation in JavaScript

Click the button below to move the image to the right

Automatic animation

In the example above, we saw how the image moves to the right with each click. We can automate this process using the setTimeout() function in JavaScript like this:

  • The moveRight() function calls the setTimeout() function to set the position imgObj.
  • We have added new feature stop() to clear the timer set by setTimeout() and set the object to its original position.
Example

Try the following code example.

Animation in JavaScript

Click the buttons below to process the animation

Rollover with mouse event

Here's a simple example showing image rollover with a mouse event.

Let's see what we use in the following example:

  • While this page is loading, the "if" statement checks for the presence of an image object. If the image object is not available, this block will not be executed.
  • The Image() constructor creates and preloads a new image object named image1.
  • The src property is set to the name of the external image file, called /images/html.gif.
  • Similarly, we have created an image2 object and assign /images/http.gif to this object.
  • The # (hash sign) disables the link to prevent the browser from trying to navigate to the URL when clicked. This link is an image.
  • The OnMouseOver event handler is called when the user moves the mouse on the link, and the onMouseOut event handler is called when the user's mouse moves away from the line (image).
  • When the mouse moves over the image, the image changes from the first image to the second. When the mouse moves away from the image, the original image is displayed.
  • When the mouse is moved away from the link, the original html.gif image will appear on the screen.
Rollover with mouse events

Hover over the image to see the result

Back in the day, most developers used jQuery to animate elements in the browser. Discolor this, stretch that - simple things. But as interactive projects became more aggressive and mobile devices burst onto the scene, performance became the most important factor.

Flash gradually fell out of favor, and talented animators made HTML5 do things it had never done before. They needed more efficient tools for complex effects and top-notch performance.

jQuery just wasn't designed for this. Browsers have matured and started offering solutions.

The most widely known solution is CSS animations. CSS animation, as the darling of the IT industry, has been endlessly discussed at conferences for several years, where phrases such as “hardware acceleration” and “user-friendliness” mobile devices" caressed the audience's ears.

JavaScript-based animations were seen as outdated and "obscene". But is this really so?

As someone who is fascinated (borderline obsessive, actually) with animation and performance, I eagerly jumped into the arms of CSS. And before I had gotten very far, many serious problems emerged that no one had talked about. I was shocked.

This article is intended to raise awareness of some of the most significant disadvantages of CSS-based animations, so you can avoid the headaches I experienced and make a more informed decision about when to use JS for animations and when to use CSS.

No independent scale/rotation/position control

Animating the scale, rotation, and position of an element is extremely common. In CSS, all these parameters are stuffed into the transform property, which makes it impossible to create a separate animation for each parameter of one element.

For example, what if you want to do rotation and scale animations independently of each other, with different runtime calculations and easing functions?

Maybe the element is constantly pulsating (oscillating scale) and you would like to rotate it on hover. This is only possible with JavaScript.

HTML:

Note that scale, rotation and position can be animated independently of each other, using different easing functions and overlapping start/end times (which is not possible with CSS animations).

Independent transformations Spin rotation Spin rotationX Spin rotationY wander (position)

CSS:

body ( background-color:black; margin: 0; padding: 0; font-family: Signika Negative, sans-serif; font-weight: 300; ) html, body ( height: 100%; ) #demo ( display:table ; width:100%; height:100%; ) #field ( position:relative; display:table-cell; height: 100%; overflow:hidden; text-align: center; vertical-align: middle; ) #box ( color: black; font-size: 24px; border: 2px solid black; background: linear-gradient(to bottom, #71B200 100%); block; border-radius: 10px; ) #field p ( position: absolute; color: #999; top: 0px; padding: 0px 20px; text-align: left; z-index: -1000; ) #controls ( position: absolute; color: #999; width: 100%; text-align: center;

JS:

var $box = $("#box"), $field = $("#field"), rotation = 0, rotationX = 0, rotationY = 0, wanderTween, ignoreRollovers; //apply perspective to the container so we can see 3D. TweenLite.set($field, (perspective: 500)); //shift the source along the z axis to make the rotation more interesting. TweenLite.set($box, (transformOrigin:"center center -150px")); //make the rectangle pulsate using scaleX and scaleY TweenMax.to($box, 1.2, (scaleX:0.8, scaleY:0.8, force3D:true, yoyo:true, repeat:-1, ease:Power1.easeInOut)); //on hover, we'll flip the rectangle, but to avoid excessive //rotation, we'll reduce the hover sensitivity for the first second of //the animation. $box.hover(function() ( if (!ignoreRollovers) ( rotation += 360; ignoreRollovers = true; TweenLite.to($box, 2, (rotation:rotation, ease:Elastic.easeOut)); TweenLite.delayedCall( 1, function() ( ignoreRollovers = false; ) ) ), function() ()); $("#rotation").click(function() ( rotation += 360; TweenLite.to($box, 2, (rotation:rotation, ease:Elastic.easeOut)); )); $("#rotationX").click(function() ( rotationX += 360; TweenLite.to($box, 2, (rotationX:rotationX, ease:Power2.easeOut)); )); $("#rotationY").click(function() ( rotationY += 360; TweenLite.to($box, 2, (rotationY:rotationY, ease:Power1.easeInOut)); )); $("#move").click(function() ( if (wanderTween) ( wanderTween.kill(); wanderTween = null; TweenLite.to($box, 0.5, (x:0, y:0)); ) else ( wander(); ) )); //randomly select a place on the screen and start the animation there, then repeat this //again and again. function wander() ( var x = (($field.width() - $box.width()) / 2) * (Math.random() * 1.8 - 0.9), y = (($field.height() - $box.height()) / 2) * (Math.random() * 1.4 - 0.7); wanderTween = TweenLite.to($box, 2.5, (x:x, y:y, ease:Power1.easeInOut, onComplete:wander));

In my opinion this is obvious weak side CSS, but if you're creating simpler animations that involve entire transformations at any given time, then this won't be a problem for you.

Performance

Most comparisons on the Internet pit CSS animations against jQuery library, since it's very common (as if "JavaScript" and "jQuery" were synonymous), but jQuery is widely known to be quite slow in terms of animation performance.

More new library GSAP is also based on JavaScript, but it is literally 20 times faster than jQuery. So one of the reasons JavaScript gets a bad rap is what I call the “jQuery factor”.

The most commonly cited argument for using CSS for animation is “hardware acceleration.” Sounds delicious, right?

Let's break it down into two parts:

GPU involvement

The graphics processing unit (GPU) is highly optimized for tasks such as moving pixels, applying transparency and transformation matrices, so modern browsers try to shift such tasks from central processor(CPU) to GPU.

The secret is to separate the animated elements into their own GPU layers, because once the layer is created (as long as its original pixels don't change), it's easy for the GPU to move those pixels around and combine them together.

Instead of calculating each individual pixel 60 times per second, the GPU can store groups of pixels (as layers) and simply say, “Move this group 10 pixels and 5 pixels down” (or something like that).

Note: It is not wise to give each element its own layer because the GPU has limited video memory. If you go beyond it, everything will slow down dramatically.

Declaring animations in CSS allows the browser to determine which elements should receive GPU layers and distribute them accordingly. Great!

But did you know that with JavaScript you can do this too? Setting a transform with a 3D characteristic (such as translate3d() or matrix3d() ) causes the browser to create a GPU layer for that element. So the GPU speed boost doesn't just work for CSS animations—JavaScript animations can benefit from it too!

Also note that not all CSS properties are GPU accelerated in CSS animations. In fact, most of them do not receive this acceleration. Transformations (scale, rotation, shear and skew) and transparency are the main operations that benefit from GPU acceleration.

So don't think that if you create animations with CSS, everything will magically become GPU accelerated. This is simply not true.

Redistributing calculations to another thread

Another part of "hardware acceleration" relates to the ability to use different CPU threads for calculations related to animation. Again, this sounds great in theory, but it doesn't come without a cost, and developers often overestimate the benefits gained.

First of all, only those properties that do not affect the flow of the document can actually be passed to another thread.

So again, transformation and transparency are the main beneficiaries. When threads are forked, there is an overhead associated with managing this process.

Since graphics rendering and document layout eat up most of the processing power (much more) in most animations (not counting intermediate animation property values), the benefit of using a separate thread for interpolation is minimal.

For example, if 98% of the work during a certain animation is rendering graphics and document layout, and 2% is figuring out new position/rotation/transparency/whatever values, even calculating them 10 times faster, overall you'll only see about 1 % speed increase.

Performance Comparison

The stress test below creates a certain number of image elements (dots) and sets them in motion from the center to a random location near the edges using random delays, thereby creating the effect of flying through the stars.

Set a large number of points and see a comparison of jQuery, GSAP and Zepto.

Because Zepto uses CSS transformations for all animations, its performance should be the best, right?

HTML:

  • Engine: jQuery (JS) GSAP (JS) Zepto (CSS)
  • Properties: top, left, width, height transform:translate(...) scale(...)
  • Dots: 25 50 100 200 300 400 500 750 1000 1250 1500 2000 2500 3000
  • START
  • HTML5 animation speed testing

    Compare the performance of animations based on jQuery, GSAP (GreenSock Animation Platform), and CSS transformations (which are used in Zepto). Select the options above and press "START". Increase the number of dots until you see choppy movements or clumps/circles. Also note which properties animate faster: "top", "left", "width" and "height" or "transform: translate(...) scale(...)". You might be surprised.

    CSS:

    body ( background-color: black; margin:0; padding:0; color:#eee; font-family: Signika Negative, sans-serif; font-weight: 300; font-size: 1.15em; user-select:none ; -webkit-user-select:none; ) html, body ( height: 100%; overflow: hidden; ) h1 ( font-weight: 400; font-size:2em; line-height:1em; margin-bottom:0.1 em; color: white; ) a, a:hover, a:visited ( color:#71B200; ) #controls ( display:table-row; background-color:#555; background: linear-gradient(to bottom, #777 0%,#444 100%); padding:10px 10px 10px 5px; z-index:1000; ) #controls form li ( display:table-cell; padding:12px 6px 10px 6px; vertical-align:middle; text-shadow : 1px 1px 1px #000; ) #instructions ( width:82%; margin-left:8%; padding-top:1em; line-height: 1.5em; color:#ccc; ) #demo ( display:table; width :100%; height:100%; ) #field ( position:relative; display:table-cell; width:100%; height: 100%; overflow:hidden; z-index:-100; border-top: 1px solid #777; ) #start ( color: black; border-radius: 6px; padding: 5px 18px; border: 2px solid black; background: #9af600; background: linear-gradient(to bottom, #9af600 0%,#71B200 100%); cursor: pointer; text-shadow: none; font-weight: 400; )

    JS:

    var $start = $("#start"), $dotQtyInput = $("#dotQuantity"), $engineInput = $("#engine"), $propertiesInput = $("#properties"), $instructions = $( "#instructions"), $field = $("#field"), $window = $(window), $inputs = $("select"), inProgress = false, tests = (), duration, radius, centerX, centerY, dots, rawDots, currentTest, startingCSS; /** * The purpose of this test is to compare how different animation tools perform under load, taking relatively common animation tasks and running them in large numbers to see raw performance. The goal is not to figure out the most efficient way to move points in a star field pattern. * * The same code is used in everything except the animations themselves. Each test in the “test” object has 4 properties: * * - milliseconds – true if the duration should be specified in milliseconds * * - wrapDot – when each point is created, it must be passed to the wrapDot() method and what is returned by the function is stored in an array of dots for animation. This is useful for improving the performance of things like jQuery, because instead of passing the element's DOM to the tween() method (which would require jQuery to query the DOM and wrap the element in an engine-specific object before calling animate()), a natural object can be used. Simply put, this will allow point wrapping to be cached to improve performance. * * - tween is the core of the entire test. tween() is called for each point, the point is passed as a parameter. The tween() function should set the point's cssText to the startingCSS value (which simply places the point in the middle of the screen and sets its width and height to 1 pixel) and then after a random delay of 0 to the animation's execution time, the function should animate the point under a random angle by changing either the left/top values ​​or the translate() transforms, and set the size to 32 pixels in width and height using either width/height or scale(). Then, after the animation is complete, the tween() method must be called again on the same point. So the same point will simply constantly move away from the center at a random angle and with a random delay time. * * - stop – this function is called when the user stops the test. The point is passed as a parameter. The function should immediately stop/destroy the animation (or animations) running for this point (or for all points - this is also normal). * * - nativeSize – true if the initial width/height of the images should be natural size (usually necessary for transformations, but not when we animate the width/height). * *I don't claim to be an expert in the various animation engines, so if there are optimizations that can be applied to improve test performance, please let me know. I tried to do everything as impartially as possible. **/ //standard jQuery normal (top/left/width/height) tests.jquery_normal = ( milliseconds:true, wrapDot:function(dot) ( return jQuery(dot); //wrap the point in a jQuery object to improve performance ( this way we don't have to query the DOM every time we animate - we can just call animate() directly on the jQuery object), tween:function(dot) ( var angle = Math.random() * Math.PI * 2 ; dot.style.cssText = startingCSS; dot.delay(Math.random() * duration).animate((left:Math.cos(angle) * radius + centerX, top:Math.sin(angle) * radius + centerY , width:32, height:32), duration, "cubicIn", function() ( tests.jquery_normal.tween(dot) )), stop:function(dot) ( dot.stop(true); ), nativeSize :false); //standard GSAP (top/left/width/height) tests.gsap_normal = ( milliseconds:false, wrapDot:function(dot) ( return dot; //no need for wrapping), tween:function(dot) ( var angle = Math.random() * Math. PI*2; dot.style.cssText = startingCSS; TweenLite.to(dot, duration, (css:(left:Math.cos(angle) * radius + centerX, top:Math.sin(angle) * radius + centerY, width:32, height:32), delay:Math .random() * duration, ease:Cubic.easeIn, overwrite:"none", onComplete:tests.gsap_normal.tween, onCompleteParams:)); ), stop:function(dot) ( TweenLite.killTweensOf(dot); ), nativeSize:false ); //GSAP transformations (translate()/scale()) tests.gsap_transforms = ( milliseconds:false, wrapDot:function(dot) ( return dot; // no need for wrapping), tween:function(dot) ( var angle = Math.random() * Math.PI * 2; TweenLite.set(dot, (css:(x:0, y:0, scale:0.06), overwrite:"none")); , (css:(x:(Math.cos(angle) * radius), y:(Math.sin(angle) * radius), scaleX:2, scaleY:2), delay:Math.random() * duration, ease:Cubic.easeIn, overwrite:"none", onComplete:tests.gsap_transforms.tween, onCompleteParams:)); stop:function(dot) ( TweenLite.killTweensOf(dot); ), nativeSize:true); //standard Zepto (top/left/width/height) tests. zepto_normal = ( milliseconds:true, wrapDot:function(dot) ( return Zepto(dot); // wrap the dot in a jQuery object to improve performance (so we no need to query the DOM every time we animate - we can just call animate() directly on the jQuery object), tween:function(dot) ( var angle = Math.random() * Math.PI * 2; dot.style .cssText = startingCSS; //Zepto's delay function works HORRIBLY under pressure, so we use setTimeout() instead to improve performance. setTimeout(function() ( if (!dot.isKilled) ( //Zepto doesn't have a function, which would allow us to kill running animations, so we simply set our own isKilled property to true when the animation is assumed to have stopped and then stop the recursion, which gives us the effect we need dot.animate((left:Math.cos(angle) * radius + centerX, top:Math.sin(angle) * radius + centerY, width:32, height:32), duration, "cubic-bezier(0.550, 0.055, 0.675, 0.190)", function() ( tests. zepto_normal.tween(dot)); ) ), duration * Math.random()); ), stop:function(dot) ( dot.isKilled = true; ), nativeSize:false ); //Zepto transformations (translate()/scale()) tests.zepto_transforms = ( milliseconds:true, wrapDot:function(dot) ( return Zepto(dot); // wrap the dot in a jQuery object to improve performance (so we no need to query the DOM every time we animate - we can just call animate() directly on the jQuery object) ), tween:function(dot) ( // I couldn't set css function () in Zepto (it failed), so I had to use a zero-duration animate() call. Although this is fair, because for TweenLite we, in fact, also make animation of zero duration. dot.animate((translateX:"0px", translateY:"0px", rotateY:"0rad", rotateX:"0rad", scale:"0.06,0.06"),0); // Zepto's delay function works HORRIBLY under pressure, so we use setTimeout() instead to improve performance. setTimeout(function() ( if (!dot.isKilled) ( //Zepto doesn't have a function that allows us to kill running animations, so we simply set our own isKilled property to true when we assume the animation has stopped and then stop recursion, which gives us the desired effect. var angle = Math.random() * Math.PI * 2; dot.animate((translateX:(Math.cos(angle) * radius) + "px", translateY:(Math. sin(angle) * radius) + "px", scale:"2.2", delay:duration * Math.random()), duration, "cubic-bezier(0.550, 0.055, 0.675, 0.190)", function( ) ( tests.zepto_transforms.tween(dot); ) ) ), duration * Math.random()); ), stop:function(dot) ( dot.isKilled = true; ), nativeSize:true ); function toggleTest() ( var i, size; inProgress = !inProgress; if (inProgress) ( $inputs.prop("disabled", true); $field.css((pointerEvents:"none")); //improving performance – ignore pointer events during animation $start.html(" STOP "); $start.css((background:"#C00")); TweenLite.to($instructions, 0.7, (autoAlpha:0, overwrite:"all ")); currentTest = tests[$engineInput.val() + "_" + $propertiesInput.val()]; size = (currentTest.nativeSize ? "16px" : "1px"); centerX = $field.width( ) / 2; centerY = $field.height() / 2; startingCSS = "position:absolute; left:" + centerX + "px; top:" + centerY + "px; width:" + size + "; height: " + size + ";"; radius = Math.sqrt(centerX * centerX + centerY * centerY); duration = currentTest.milliseconds ? 750: 0.75; //wait a millisecond before creating points and starting animation, so the UI plays forward (turning the "start" button into a "stop"), otherwise users might get confused during the long pause while Zepto is selected and converting, due to the fact that it may take some time for the browser to place all the dots on their own layers. setTimeout(function() ( createDots(); i = dots.length; while (--i > -1) ( currentTest.tween(dots[i]); ) ), 1); ) else ( $start.html(" START "); $start.css((backgroundColor:"#9af600", background: "linear-gradient(to bottom, #9af600 0%,#71B200 100%")); TweenLite .to($instructions, 0. 7, (autoAlpha:1, delay:0.2)); $inputs.prop("disabled", false); calibrateInputs(); $field.css((pointerEvents:"auto")); //stop the animation and delete the points. i = dots.length; while (--i > -1) ( currentTest.stop(dots[i]); $field.removeChild(rawDots[i]); //removes a point (or points) ) dots = null; rawDots = null; ) ) function createDots() ( var i = parseInt($dotQtyInput.val()), dot; dots = ; rawDots = ; while (--i > -1) ( dot = document.createElement("img"); dot .src = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/dot.png"; dot.width = 1; dot.id = " dot" + i; dot.style.cssText = startingCSS; $field.appendChild(dot); rawDots.push(dot); dots.push(currentTest.wrapDot(dot)); ) ) function calibrateInputs(e) ( if ( $engineInput.val() === "jquery") ( //jQuery can't animate transformations without a third party plugin, so disable this option $propertiesInput.selectedIndex = 0; $propertiesInput.prop("disabled", true); ) else ( $propertiesInput.prop("disabled", false); ) ) $start.click(toggleTest); $inputs.change(calibrateInputs); jQuery.easing.cubicIn = $.easing.cubicIn = function(p, n, firstNum, diff) ( //we need to add the standard CubicIn easing function to jQuery return firstNum + p * p * p * diff; ) jQuery.fx. interval = 16; //ensures that jQuery updates at approximately 60 frames per second, like GSAP and others, to show a more equal/unbiased result. $propertiesInput.prop("disabled", true);

    The results confirm what is widely noted on the Internet - CSS animations are significantly faster than jQuery.

    However, on most devices and browsers I've tested on, JavaScript-based GSAP has even better performance than CSS animations (by a large margin in some cases, such as on the Microsoft Surface RT where the GSAP library was at least 5 times faster) faster than CSS transformations created with Zepto, and on iPad 3 with iOS7 transformations were much faster when done with GSAP instead of CSS transformations):

    Animated Properties Better with JavaScript Better with CSS
    top, left, width, height Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS 6), iPad 3 (iOS7), Samsung Galaxy Tab 2, Chrome, Firefox, Safari, Opera, Kindle Fire HD, IE11
    transformations (shift/scale) Windows Surface RT, iPhone 5s (iOS7), iPad 3 (iOS7), Samsung Galaxy Tab 2, Firefox, Opera, IE11 iPad 3 (iOS6), Safari, Chrome

    How much faster? The original version of the test had a frames per second counter to provide quantitative results, but I soon discovered that there was no truly accurate way to measure this in all browsers, especially with CSS animations, and some browsers produced misleading data, so I removed this function.

    Although you can easily evaluate relative performance by increasing the number of points, switching between engines and observing how the animation is executed (smoothness of movement, uniformity of time intervals, distribution of points, etc.). At the end of the day, the main goal is to get presentable animations.

    Interesting to note:

    • When animating the top/left/width/height properties (which affect document flow), JavaScript was faster across the board (GSAP, not jQuery);
    • Some devices were well optimized for transformations, while others were better at handling animations with top/left/width/height properties. In particular, the older iOS6 performed CSS-based transformations much better, but the new iOS7 has changed priorities and now they are much slower;
    • There is a significant delay in the initial launch of CSS-based animations as the browser calculates the layers and loads the data into the GPU. This also applies to 3D transformations in JavaScript, so "GPU acceleration" is not lossless;
    • Under heavy CSS loads, transformations are more likely to be sprayed into stripes or rings (this is due to synchronization and scheduling issues, possibly due to control on another thread);
    • In some browsers (for example, Google Chrome), when a very large number of points were involved in the animation, there was absolutely no gradual fading of the text, but this only happened when using CSS animations!

    While well-optimized JavaScript is often as fast, if not faster, than CSS animations, 3D transformations are typically rendered using CSS, but this is directly related to how browsers handle 16-element matrices (forcing conversion from numbers to concatenated line, and then back to numbers).

    Let's hope that changes though. Be that as it may, in most real-life projects you would never notice the difference in performance.

    I encourage you to do your own testing to see which technology will provide smooth animation in your specific project(s).

    Don't buy into the myth that CSS animations are always faster, and don't assume that the speed test above reflects what you'll see in your application. Test, test and test again.

    Execution Controls and Events

    Some browsers allow you to stop or restart animations with CSS keyframes, but that's about it.

    You can't access a specific location in an animation, just like you can't smoothly change the direction of a section of animation, or change the timeline, or add callbacks at specific locations, or bind them to a rich set of playback events.

    JavaScript, on the other hand, gives you a lot of control, as you can see in the example below.

    HTML:

    Not possible with CSS animations. play reverse restart Speed: slow normal fast

    CSS:

    body ( font-family: Signika Negative, sans-serif; font-weight: 300; color: white; background-color: black; text-align: center; ) #demo ( text-align: center; margin-top:20px ; ) #bg ( background-color:#000; position:relative; overflow:hidden; display:inline-block; width:500px; height:70px; border-radius: 8px; border: 2px solid #777; ) #text ( position:absolute; text-align:center; width:500px; height:70px; line-height:68px; font-size: 28px; ) #text span ( -webkit-font-smoothing: antialiased; -moz-font- smoothing:antialiased; position:relative; display:inline-block; ) #slider ( display: inline-block; width: 500px; height:12px; margin:8px 0px 8px 6px; ) #controls button : 80px; ) #controls input ( display:inline; padding:2px; margin:2px; )

    JS:

    var $text = $("#text"), $pause = $("#pause"), $reverse = $("#reverse"), $restart = $("#restart"), $speed = $( "input"), $slider = $("#slider"), //"tl" is the scale to which we will add our animation. //Then we can easily control the entire animation sequence as one object. tl = new TimelineLite((onUpdate:updateSlider, onComplete:onComplete, onReverseComplete:onComplete, paused:true)); function updateSlider() ( $slider.slider("value", tl.progress() * 100); ) function onComplete() ( tl.pause(); $pause.html("play"); ) //do something simple splitting the text so we can apply animation to each //character (don't need the advanced SplitText functions, so just use split() and //join()) $text.html("" + $text.html().split( "").join("").split("").join("") + ""); //set the perspective on the container TweenLite.set($text, (perspective:500)); //all animation is created in one line: tl.staggerTo($("#text span"), 4, (transformOrigin:"50% 50% -30px", rotationY:-360, rotationX:360, rotation:360, ease :Elastic.easeInOut), 0.02); //control the slider and button $slider.slider(( range: false, min: 0, max: 100, step:.1, slide: function (event, ui) ( tl.progress(ui.value / 100).pause (); $pause.html("play"); $pause.click(function() ( if (tl.paused()) ( if (tl.progress() === 1 || (tl.progress() === 0 && tl.reversed())) ( tl.restart(); ) else ( tl.resume(); ) $pause.html("pause"); else ( tl.pause(); $pause.html("resume"); ) )); $reverse.click(function() ( if (tl.progress() === 0) ( if (tl.reversed()) ( tl.play(); ) else ( tl.reverse(0); ) $pause .html("pause"); ) else ( tl.reversed(!tl.reversed()).resume(); $pause.html("pause"); ) )); $restart.click(function())( tl.restart(); $pause.html("pause"); )); $speed.change(function(v, val) ( tl.timeScale(parseFloat($(this).val())); if (tl.progress() === 1) ( tl.restart(); $pause .html("pause"); ) else if (tl.paused()) ( tl.resume(); $pause.html("pause"); ) ));

    Modern animation is very much about interactivity, so it's incredibly useful to be able to animate from mutable initial values ​​to mutable final values ​​(depending on where the user clicks, for example) or change something on the fly, but declarative animations are CSS-based ones don't allow you to do this.

    Workflow

    For simple transitions between two states (for example, flipping or expanding a menu, etc.) CSS transformations are great.

    However, for a sequence of events, you will typically need to use CSS animations with keyframes, which will require percentage selectors, for example:

    CSS:

    @keyframes myAnimation ( 0% ( opacity: 0; transform: translate(0, 0); ) 30% ( opacity: 1; transform: translate(0, 0); ) 60% ( transform: translate(100px, 0); ) 100% ( transform: translate(100px, 100px); ) ) #box ( animation: myAnimation 2.75s; )

    But when you create an animation, don't you focus on time intervals rather than percentages? For example, "increase transparency for 1 second, then slide to the right for 0.75 seconds, and then jump down for the remaining second."

    What happens if you spend hours calculating a complex sequence as a percentage, and the client then says, "Make that part in the middle 3 seconds longer"? Ugh, you'll have to recalculate ALL the percentages!

    Typically, building animations involves a lot of experimentation, especially with timing and easing functions.

    This is relevant where the seek() method would be quite useful. Imagine creating a 60-second animation piece by piece and then honing in on the final 5 seconds: you'd have to sit through the first 55 seconds every time you wanted to see the result of your adjustments in the final parts.

    Ugh! With the seek() method, you could simply reference a specific location in the animation as you work to get to the part you're working on, and then delete it when you're done. This is a significant time saving.

    Creating animations for canvas-based objects and other third-party library objects is becoming widespread, but, unfortunately, CSS animations are only intended for DOM elements.

    This means that if you've invested a lot of time and energy into CSS animations, they won't be transferable to other types of projects.

    You will have to change your animation toolset.

    There are several more convenient tools Workflow related ones that are missing from CSS animations:

    • Relative values. For example, “make the rotation 30 degrees more” or “move the element down 100 pixels from where it was when the animation started”;
    • Nesting. Imagine being able to create animations that can be nested within another animation, which itself can be nested, etc. Imagine controlling the main animation while everything else remains completely in sync. Such a structure would encourage modular code that is much easier to create and maintain;
    • Progress report. Is a particular animation complete? If not, what stage of execution is it exactly at?
    • Targeted eliminations. Sometimes it's incredibly useful to disable all animations that affect the scale of an element (or any other property you want) while allowing all the others;
    • Short code. Keyframe-based CSS animations are verbose, even without all the redundant vendor-prefixed versions required. Anyone who has tried to create anything of even moderate complexity will attest to the fact that CSS animations quickly become unwieldy and clunky. In fact, the actual amount of CSS code required to perform animation tasks may exceed the weight of the JavaScript library (which is easier to cache and reuse across many animations).
    Limited effects

    You will not be able to do any of the following when CSS help animations:

    • Animation along a curve (for example, a Bezier curve);
    • Use interesting softening functions such as elastic, springy or rough softening. There is a cubic-bezier() option, but it only allows two key points, which is very limiting;
    • Movements according to physical laws. For example, smooth movement based on inertia and easy return back, implemented in this Draggable demo;
    • Scroll position animation;
    • Directional turn (for example, "turn exactly 270 degrees in the shortest direction, clockwise or counterclockwise");
    • Attribute animation.
    Compatibility

    CSS-based animations do not work in IE9 and earlier browser versions. Most of us hate providing support for legacy browsers (especially IE), but the reality is that some of us have clients that require it.

    Applying prefixes is necessary for many browsers, but you can use preprocessing tools to avoid having to write them manually.

    Conclusion

    Are CSS Animations Bad? Definitely not. In fact, they are great for simple state transitions (such as flipping) where compatibility with legacy browsers is not required.

    3D transformations generally have good performance (iOS7 is a notable exception) and CSS animations can be very attractive to developers who prefer to put all the animation and presentation logic into a CSS layer.

    However, JavaScript-based animations provide much greater flexibility, a more comfortable development process for complex animations, and rich interactivity, and often JavaScript-based animations are as fast (or even faster) than CSS-based animations, even though you you may have heard.

    I can see why CSS animations were so attractive compared to jQuery.animate() . Who in their right mind wouldn't jump at the opportunity to get a 10x increase in productivity?

    There's no longer a need to choose between jQuery and CSS animations; JavaScript-based tools like GSAP open up entirely new possibilities and close the performance gap.

    This article is not about GSAP or any specific library; The moral of the article is that JavaScript-based animations don't deserve the bad rap. In fact, JavaScript is the only option for a truly robust and flexible animation system.

    Plus, I wanted to shed some light on some of the frustrating aspects of CSS animations (that no one talks about) so you can now make more informed decisions about how to create animations.

    Will the Web Animations specification solve existing problems?

    The W3C is working on a new specification called "Web Animations" that aims to address many of the shortcomings in CSS animations and transformations, providing better execution control and additional functionality.

    Of course, this seems like a step forward in many respects, but there are still a number of shortcomings (some of which are probably impossible to overcome due to the need to support older versions of existing CSS specifications, so, for example, independent control of transform components is unlikely).

    Although this is a completely different story. We need to wait and see how things work out. There are certainly smart guys working on this specification.

    This publication is a translation of the article “Myth Busting: CSS Animations vs. JavaScript" prepared by the friendly project team

    Abstract: A simple example: the yellow fading method. Animation using JavaScript libraries. More complex example: Move and resize. CSS transitions.

    The principle behind fading is that the background color of the fading element is set to yellow, and then, through a series of steps, its color returns to its original color. So if the original background color was red, then the color is then set to yellow, then orange-yellow, then orange, then red-orange, and then red. The number of steps used determines how smoothly the color change occurs, and the time between steps determines how long the color change continues. When changing colors, a useful fact from CSS can be used: a color can be defined as a triple of regular numbers or as a hexadecimal string. Therefore #FF0000 (red color) can also be defined as rgb(255,0,0) . Changing from yellow to red in five steps means, therefore, going from rgb(255,255,0) (yellow) to rgb(255,0,0) in the following five steps:

    rgb(255,255,0) rgb(255,192,0) rgb(255,128,0) rgb(255,64,0) rgb(255,0,0)

    More complex example: moving and resizing

    Although the yellow fading method demonstrates animation, it is somewhat boring. When most people think of animation, they usually think of movement. An interesting technique for alerting the user that something has happened without interrupting their workflow is to use a modeless message. Instead of displaying an alert() dialog that requires the user to click OK before they can continue, place the message simply in a floating div on the page that unobtrusively stays there until it receives confirmation. The second one is enough interesting thing this could then be to allow the user to return to a message for which they have confirmed they wish to read it again. So let's implement a floating message that, when clicked, collapses to the corner of the screen and can then be restored again when clicked. You can watch a short demo of this "collapsing message" (http://dev.opera.com/articles/view/javascript-animation/moving_messages_jq.html) to get the general idea.

    If you're doing some serious animation work, or some serious JavaScript work, it's almost always worth using a JavaScript library. This will allow you to create the desired presentation for users without having to worry about the mathematical intricacies required to perform the animation. (With the first example above, you now know how to do the math and how to use setInterval , but you'll save time and effort by using ready-made solutions.)

    The demo above uses the jQuery library (http://jquery.com/) to work, but as mentioned, most libraries provide a similar enough animation concept that you should be able to implement the fundamental part using your preferred library. Essentially, you need to do the following:

  • Show a floating message in the center of the screen
  • When it is clicked:
  • Move its horizontal position to the far right position
  • Move its vertical position up
  • Set its width to 20px
  • Set its height to 20px
  • Make its density equal to 20%, so that it becomes almost transparent and hide the text in it
  • When this "mini" version of the message is clicked, restore it to the center of the screen (i.e., the opposite of what we did to compress it) and so that the user gets a clear picture of what happened to their message, jumping from the full size The messages to the mini-message should be animated (so they can see the message "shrink" into the corner of the window).
  • Perform animation with using jQuery very easy: just use the . animate() and provide the desired end result of the animation (and how long it should run):

    $(ourObject).animate(( width: "20px", height: "20px", top: "20px", right: "20px", marginRight: "0px", opacity: "0.2" ), 300);

    The function takes ourObject and, in 300 milliseconds, replaces its width and height with 20px, its top and right positions with 20px, its margin-right style property with 0px, and its density (in browsers that support image density) with 20%. Then it's just a matter of programming in style

    Learn to create HTML animations with using JavaScript.

    Basic web page

    To demonstrate how to create HTML animations with JavaScript, we'll use a simple web page:

    Creating a Container Animation

    All animations must be relative to the container element.

    Style Elements

    The container element must be created with style="position:relative".

    The animation element must be created with style="position:absolute".

    example

    #container (
    width: 400px;
    height: 400px;
    position: relative;
    background: yellow;
    }
    #animate (
    width: 50px;
    height: 50px;
    position: absolute;
    background:red;
    }

    Try it yourself " Animation Code

    JavaScript animations are performed by programming gradual changes in the style of an element.

    Changes are triggered using a timer. When the timer interval is small, the animation appears continuous.

    Main code:

    example

    function frame() (
    if (/* test for finished */) (
    clearInterval(id);
    ) else (
    /* code to change the element style */
    }
    }

    Creating Animation Using JavaScriptExample

    Function myMove() (
    var elem = document.getElementById("animate");
    var pos = 0;
    var id = setInterval(frame, 5);
    function frame() (
    if (pos == 350) (
    clearInterval(id);
    ) else (
    pos++;
    elem.style.top = pos + "px";
    elem.style.left = pos + "px";


    Close