Velocity.js|GitHub
Accelerated JavaScript animation.
-
Overview
Velocity is an animation engine with the same API as jQuery's $.animate(). It works with and without jQuery. It's incredibly fast, and it features color animation, transforms, loops, easings, SVG support, and scrolling. It is the best of jQuery and CSS transitions combined. -
Download
Download Velocity, include it on your page, and replace all instances of jQuery's $.animate() with $.velocity(). You will immediately see a performance boost across all browsers and devices — especially on mobile. -
Compatibility
Velocity works everywhere — back to IE8 and Android 2.3. Under the hood, it mimics jQuery's $.queue(), and thus interoperates seamlessly with jQuery's $.animate(), $.fade(), and $.delay(). Since Velocity's syntax is identical to $.animate(), your code doesn't need to change. -
Secret Sauce
JavaScript and jQuery are falsely conflated. JavaScript animation, which Velocity uses, is fast; it's jQuery that's slow. Although Velocity works alongside jQuery, it uses its own animation stack that delivers its performance through two underlying principles: 1) synchronize the DOM → tween stack to minimize layout thrashing, and 2) cache values to minimize DOM querying. -
Check this out
Read my engineer's guide to growing your startup. -
Who uses Velocity?
Libscore lists some of Velocity's biggest users.
-
More from Julian Shapiro
I spent a year summarizing the tactics of acquiring users.
-
Performance
FPS
Click here to see a comparison between jQuery and Velocity animating a dialog box. You can view the code that powers this comparison.
Load
Velocity outperforms jQuery at all levels of stress, and outperforms Transit (the leading CSS animation library) beginning at medium levels of stress.
The following real-world demo animates the chosen number of divs using this common property map:
{ left: "85%", opacity: 1 }
.You can view the code that powers this comparison.
If all engines behave sluggishly at low element counts, your browser or device may need a restart. Browser animation performance is affected by your system's memory and CPU consumption.
-
CSS Support
-
Resources
Demos
- Watch (10min) a tutorial explaining how this 3D demo was built in Velocity.
- Watch (5min) a tutorial explaining how Velocity's UI pack improves user interfaces.
- Visit Velocity's demo gallery.
Articles
- Read the technical overview of Velocity's performance gains over CSS and jQuery.
- Read the technical breakdown of Velocity's performance optimizations.
- Read an introduction to SVG animation using Velocity.
- Read about how you can animate in Velocity without jQuery.
Credits
- Thanks to Stripe for sponsoring Velocity's development.
- Thanks to BrowserStack for providing testing services.
- Thanks to Yehonatan Daniv for providing user support on GitHub.
-
Basics: Bugs
-
Basics: Performance
Never use jQuery's $.animate() and $.fade() functions. They slow everything else down, including other animation libraries.
Always use Velocity's built-in solutions instead of rolling your own (or relying on jQuery): looping, reversing, delaying, hiding/showing elements, property math (+, -, *, /), and hardware acceleration can all be done within Velocity. Refer to the documentation below.
-
Basics: Dependencies
Update
Velocity has reached 1.0.0. Three important changes have occurred:
- jquery.velocity.js has been renamed to velocity.js since Velocity no longer requires jQuery to function. If you are still using jQuery with Velocity, you do not need to change anything in your code; Velocity will behave exactly as it always has.
- Two backwards-incompatible changes have been made: 1) When accessing element(s) passed into the begin/complete/progress/promise callbacks, you must iterate through them (e.g. via $.each() or .forEach()) since they are now wrapped inside an array before being passed through. 2) The back, bounce, and elastic easings have been removed. Use spring physics instead.
- If you're using module loaders, such as RequireJS and Browserify, read the end of this section to learn how to newly load Velocity.
Using Velocity with jQuery
Velocity.js works seamlessly with jQuery; jQuery's $.animate(), $.delay(), and $.fade() functions can be used alongside Velocity. There is no performance degradation from using Velocity with jQuery.
Note that you can offset Velocity's file size by custom-building jQuery without its effects module (see jQuery on GitHub), which Velocity does not rely on. When excluding that module, remember that you can no longer use jQuery's own animation functions.
Browser support: Back to IE8 and Android 2.3. Below IE8, Velocity avoids loading, and aliases itself to jQuery's $.animate().
Using Velocity without jQuery
Velocity.js also works when jQuery is not loaded on your page. Using Velocity without jQuery removes support for IE8, making IE9 the new minimum supported version of IE.
If Zepto is present on the page, Velocity.js works with Zepto identically to how it works with jQuery; all of the documentation examples on this page equally apply.
When neither jQuery nor Zepto are present on the page, Velocity attaches itself to the window object. In this configuration, animations are triggered via Velocity's utility function, with which raw DOM elements are passed in as Velocity's first parameter:
Velocity(document.getElementById("dummy"), { opacity: 0.5 }, { duration: 1000 });
Similarly, keep in mind that the code examples on this page that demonstrate accessing the core Velocity object on jQuery's $ must be rewritten to access the global Velocity object instead. In short,
$.Velocity
now becomesVelocity
.Further, when using velocity.js without jQuery and Zepto, you inherently no longer have access to the $.queue() and $.delay() functions provided to you by those libraries. Accordingly, you'll want to delegate custom queued logic to Velocity's begin and complete callbacks, and you'll want to use Velocity's delay option for triggering delays.
For a detailed walkthrough on animating without jQuery, read the article.
Module Loader: RequireJS
1) If you're using Velocity with jQuery, shim jQuery as a dependency of Velocity. For the Velocity UI pack (optional), shim Velocity as a dependency of the UI pack.
(Keep in mind that jQuery must be global when using RequireJS with jQuery plugins; you cannot use jQuery.noConflict().)
require.config({ [tab]paths: { [tab][tab]"jquery": "/path/to/jquery-x.x.x", [tab][tab]"velocity": "path/to/velocity", [tab][tab]// Optional, if you're using the UI pack: [tab][tab]"velocity-ui": "path/to/velocity.ui" [tab]}, [tab]shim: { [tab][tab]"velocity": { [tab][tab][tab]deps: [ "jquery" ] [tab][tab]}, [tab][tab]// Optional, if you're using the UI pack: [tab][tab]"velocity-ui": { [tab][tab][tab]deps: [ "velocity" ] [tab][tab]} [tab]} });
require([ "jquery", "velocity", "velocity-ui" ], function ($, Velocity) { [tab]/* Your app code here. */ [tab]$("body").velocity({ opacity: 0.5 }); });
2) If you're using RequireJS to load Velocity with Zepto, replace "jquery" mentions with "zepto" in the configuration example above. (Tip: Zepto isn't natively compatible with module loaders, so you'll need to manually assign var $ = window.Zepto inside your RequireJS callback to populate the $ variable for usage.)
3) If you're using Velocity by itself (as in, without jQuery or Zepto), simply require Velocity as normal (without any shimmed dependencies) and animate via the utility function as described in the Using Velocity without jQuery section above.
Module Loader: Browserify
If you're using Velocity with jQuery, you must require jQuery before Velocity, and you must assign jQuery globally on the window object:
window.jQuery = window.$ = require("path/to/jquery-x.x.x.js"); require("path/to/velocity.js");
// Optional: If you're using the UI pack, require it after Velocity. (You don't need to assign it to a variable.) require("path/to/velocity.ui.js");
/* Your app code here. */ $("body").velocity({ opacity: 0.5 });
If you're using Velocity without jQuery, simply require Velocity as normal:
var Velocity = require("path/to/velocity.js"); // Optional: If you're using the UI pack, require it after Velocity. (You don't need to assign it to a variable.) require("path/to/velocity.ui.js");
/* Your app code here. */ Velocity(document.body, { opacity: 0.5 });
-
Basics: Arguments
Overview
Velocity takes a map of CSS properties and values as its first argument. An options object can optionally be passed in as a second argument:
$element.velocity({ [tab]width: "500px", [tab]property2: value2 }, { [tab]/* Velocity's default options */ [tab]duration: 400, [tab]easing: "swing", [tab]queue: "", [tab]begin: undefined, [tab]progress: undefined, [tab]complete: undefined, [tab]display: undefined, [tab]visibility: undefined, [tab]loop: false, [tab]delay: false, [tab]mobileHA: true });
Option defaults can be globally overriden by modifying $.Velocity.defaults.
Single Object
Velocity also supports a single-argument syntax (which allows for more expressive CoffeeScript code). Simply pass in a single object with properties (or p) and options (or o) members:
$element.velocity({ [tab]properties: { opacity: 1 }, [tab]options: { duration: 500 } });
Or:
$element.velocity({ [tab]p: { opacity: 1 }, [tab]o: { duration: 500 } });
Comma-Separated
Instead of passing in an options object, Velocity also accepts jQuery's comma-separated syntax — but only for the duration, easing, and complete properties: $element.velocity(propertyMap [, duration] [, easing] [, complete]).
These options can be placed in any order:
$element.velocity({ top: 50 }, 1000); $element.velocity({ top: 50 }, 1000, "swing"); $element.velocity({ top: 50 }, "swing"); $element.velocity({ top: 50 }, 1000, function() { alert("Hi"); });
-
Basics: Properties Map
Velocity auto-prefixes properties (e.g. transform becomes webkit-transform on WebKit browsers); do not prefix properties yourself.
Velocity animates one numeric value per property. Hence, you can pass in:
{ padding: 1 }
{ paddingLeft: 1, paddingRight: 1 }
But you cannot pass in
{ padding: "1 1 1 1" }
because you're providing multiple numeric values.However, Velocity includes hooks to break down the following properties that require multiple values: textShadow, boxShadow, clip, backgroundPosition, and transformOrigin. Refer to the CSS Support dropdown for a full listing of hooks.
Velocity supports the px, em, rem, %, deg, and vw/vh units. If you do not provide a unit, an appropriate one is automatically assigned — usually px, but deg in the case of rotateZ for example.
Velocity supports four value operators: +, -, *, and /. You may suffix an equals sign onto any one of them to perform relative math operations.
$element.velocity({ [tab]top: 50, // Defaults to the px unit type [tab]left: "50%", [tab]width: "+=5rem", // Add 5rem to the current rem value [tab]height: "*=2" // Double the current height });
Browser support: rem units are not supported below IE 9. vh/vw units are not supported below IE 9 or below Android 4.4.
-
Basics: Chaining
When multiple Velocity calls are stacked onto an element (or a series of elements), they automatically queue onto one another — with each one firing once its prior animation has completed:
$element [tab]/* Animate the width property. */ [tab].velocity({ width: 75 }) [tab]/* Then, when finished, animate the height property. */ [tab].velocity({ height: 0 });
-
Option: Duration
Velocity supports durations specified in milliseconds as well as jQuery's named durations: "slow", "normal", and "fast".
$element.velocity({ opacity: 1 }, { duration: 1000 }); or $element.velocity({ opacity: 1 }, { duration: "slow" });
-
Option: Easing
Overview
Velocity supports the following easing types by default:
- Pre-packaged into Velocity are jQuery UI's easings, except for the back, bounce, and elastic easing types. A bonus "spring" easing (sampled in the CSS Support pane) is also included.
- CSS3's named easings: "ease", "ease-in", "ease-out", and "ease-in-out".
- CSS3's bezier curves: Pass a four-item array of bezier points. (Refer to Cubic-Bezier.com for crafing custom bezier curves.)
- Spring physics: Pass a two-item array in the form of [ tension, friction ]. A higher tension (default: 500) increases total speed and bounciness. A lower friction (default: 20) increases ending vibration speed. Refer to Spring Physics Tester for testing values.
- Step easing: Pass a one-item array in the form of [ steps ]. The animation will jump toward its end values using the specified number of steps. See this article to learn more about step easing.
All of the above easing types are fully compatible with IE8+. (Pretty cool!)
You can either pass in the name of a packaged easing (e.g. "ease-out" or "easeInSine"), or you can pass in one of the array types:
/* Use one of the jQuery UI easings. */ $element.velocity({ width: 50 }, "easeInSine");
/* Use a custom bezier curve. */ $element.velocity({ width: 50 }, [ 0.17, 0.67, 0.83, 0.67 ]);
/* Use spring physics. */ $element.velocity({ width: 50 }, [ 250, 15 ]);
/* Use step easing. */ $element.velocity({ width: 50 }, [ 8 ]);
Per-Property Easing
Easings can also optionally be declared on a per-property basis by passing in an two-item array as the property's value. The first item is the standard end value, and the second item is the easing type:
$element.velocity({ [tab]borderBottomWidth: [ "2px", "spring" ], // Uses "spring" [tab]width: [ "100px", [ 250, 15 ] ], // Uses custom spring physics [tab]height: "100px" // Defaults to easeInSine, the call's default easing }, { [tab]easing: "easeInSine" // Default easing });
As with jQuery's $.animate(), "swing" is Velocity's default easing type.
Custom Easings (Advanced)
To register your own easing function that can be used within Velocity calls, extend the $.Velocity.Easings object with a function that takes the following properties:
- p: The call's completion percentage (decimal value).
- opts (optional): The options object passed into the triggering Velocity call.
- tweenDelta (optional): The difference between the animating property's ending value and its starting value.
$.Velocity.Easings.myCustomEasing = function (p, opts, tweenDelta) { [tab]return 0.5 - Math.cos( p * Math.PI ) / 2; };
-
Option: Queue
You can set queue to false to force a new animation call to immediately run in parallel with any currenty-active animations.
/* Trigger the first animation (width). */ $element.velocity({ width: "50px" }, { duration: 3000 }); // Runs for 3s setTimeout(function() { [tab]/* Will run in parallel starting at the 1500ms mark. */ [tab]$element.velocity({ height: "50px" }, { queue: false }); }, 1500 // 1500ms mark);
Alternatively, a custom queue — a queue that doesn't immediately start — can be created by passing queue the name of your custom queue. You can build multiple custom queues in parallel, then later start them individually via $element.dequeue("queueName") (or Velocity.Utilities.dequeue(element(s), "queueName") if you're using Velocity without jQuery).
Note that the loop option and reverse command do not work with custom and parallel queues.
Velocity uses the same queueing logic as jQuery, and thus interoperates seamlessly with $.animate(), $.fade(), and $.delay(). To learn more about Velocity's queueing behavior, read this primer.
-
Option: Begin & Complete
Pass begin a function to be triggered prior to the start of the animation.
As with complete, the begin callback is executed once per call, even if multiple elements are being animated. Further, if a call is looped, the begin callback only fires once — at the beginning of the first loop alternation.
The callback is passed the entire raw DOM (not jQuery) element array as both its context and its first argument. To access these elements individually, you must iterate over the array using jQuery's $.each() or JavaScript's native .forEach().
$element.velocity({ [tab]opacity: 0 }, { [tab]/* Log all the animated divs. */ [tab]begin: function(elements) { console.log(elements); } });
Complete is the converse of the begin option. Pass the complete option a function to be triggered once the animation has finished. The function is executed once per call, even if multiple elements are being animated at once. Further, if a call is looped, the complete callback only fires once — at the end of the last loop alternation.
The callback is passed the entire raw DOM (not jQuery) element array as both its context and its first argument. To access these elements individually, you must iterate over the array using jQuery's $.each() or JavaScript's native .forEach().
$element.velocity({ [tab]opacity: 0 }, { [tab]/* Log all the animated divs. */ [tab]complete: function(elements) { console.log(elements); } });
-
Option: Progress
Pass the progress option a callback function to be repeatedly triggered througout the duration of an animation. The callback function is passed data on the status of the call. This data can be leveraged for custom tweening and more.
The callback is passed the entire raw DOM (not jQuery) element array as both its context and its first argument. To access these elements individually, you must iterate over the array using jQuery's $.each() or JavaScript's native .forEach(). Further, it's passed: complete, remaining, start, and tweenValue:
- complete: The call's completion percentage (as a decimal value).
- remaining: How much time remains until the call completes (in ms).
- start: The absolute time at which the call began (in Unix time).
- tweenValue: The current value of the dummy tween animation property, which can optionally be passed into a Velocity call. The utility of passing in the tween animation property is that it allows you to then capture the exact value of its tween progression via the progress callback. This dummy property, like all other Velocity animation properties, is subject to the call's easing behavior. Leveraging this tween property allows you to turn Velocity into a custom tweening engine so that you animate the change of arbitrary DOM properties.
$element.velocity({ [tab]opacity: 0, [tab]tween: 1000 // Optional }, { [tab]progress: function(elements, complete, remaining, start, tweenValue) { [tab][tab]console.log((complete * 100) + "%"); [tab][tab]console.log(remaining + "ms remaining!"); [tab][tab]console.log("The current tween value is " + tweenValue) [tab]} });
Note that you can pass the dummy tween value along with other properties as well; tween doesn't have to stand alone. Further, note that you can forcefeed the tween property to start from an arbitrary offset. If you don't forcefeed a starting value, the tween will start from a value of 0.
$element.velocity({ [tab]tween: [ 0, 1000 ] }, { [tab]easing: "spring", [tab]progress: function(elements, c, r, s, t) { [tab][tab]console.log("The current tween value is " + t) [tab]} });
-
Option: mobileHA
mobileHA stands for mobile hardware acceleration. When set to true — its default value — Velocity animations are automatically hardware accelerated on mobile devices.
Use mobileHA instead of sprinkling null transform hacks throughout your code. Velocity's manipulation of HA is highly streamlined.
Mobile browsers benefit hugely from HA, whereas desktop browsers do not. (JavaScript-powered desktop animations actually perform worse when hardware acceleration is applied.) Accordingly, mobileHA has no effect on desktop browsers.
As with Velocity's transform support — transform values set outside of Velocity (including their default values) are overridden when mobileHA is on. If this is an issue, turn mobileHA off by setting it to false:
$element.velocity(propertiesMap, { mobileHA: false });
-
Option: Loop
Set the loop option to an integer to specify the number of times an animation should alternate between the values in the call's property map and the element's values prior to the call:
$element.velocity({ height: "10em" }, { loop: 2 });
Above, if the element's original height was 5em, its height will alternate between 5em and 10em two times.
If the begin or complete callbacks are used with a looped call, they are triggered once each — at the very beginning of the loop animation and at the very end of the loop animation, respectively. They are not re-triggered for each loop alternation.
Instead of passing in an integer, you can pass in true to trigger infinite looping:
$element.velocity({ height: "10em" }, { loop: true });
Infinite loops never return promises, ignore the complete callback, and cannot be used with queue: false. Further, be sure to stop one infinite loop before triggering another infinite loop on the same element. (A loop can be stopped with the Stop command.)
-
Option: Delay
Specify the delay option in milliseconds to insert a pause before an animation begins. The delay option exists so that animation logic can be kept entirely within Velocity — as opposed to sprinkling jQuery's $.delay() throughout your code.
You can set the delay option alongside the loop option to create a pause between loop alternations:
$element.velocity({ [tab]height: "+=10em" }, { [tab]loop: 4, [tab]/* Wait 100ms before alternating back. */ [tab]delay: 100 });
-
Option: Display & Visibility
Intro
Velocity's display and visibility options correspond directly to their CSS counterparts, and therefore accept the same values: display accepts "inline", "inline-block", "block", "flex", "" (empty quotes to remove the property altogether), and whatever else the browser natively supports. visibility accepts "hidden", "visible", "collapse", and "" (empty quotes to remove the property altogether). For a comparison between the behaviors of display, visibility, and opacity, see this post.
Exclusive to Velocity, the display option also takes a non-standard value of "auto", which instructs Velocity to set the element to its native display value. For example, anchor elements default to "inline" whereas div elements default to "block".
Velocity's incorporation of CSS display/visibility changing allows for all of your animation logic to be contained within Velocity, meaning you no longer have to sprinkle jQuery's $.hide() and $.show() functions throughout your code.
Usage
When the display option is set to "none" (or when visibility is set to "hidden"), the CSS property is set accordingly after the animation has completed. This works to hide the element upon animation completion, and is useful when animating an element's opacity down to 0. (When these options are used with the loop option, they are set at the end of the final loop iteration.)
Here, an element is removed from the page's flow once it has faded out. This replaces jQuery's $.fadeOut() function:
/* Animate down to zero then set display to "none". */ $element.velocity({ opacity: 0 }, { display: "none" });
Here, an element is made invisible once it has faded out:
/* Animate down to zero then set visibility to "hidden". */ $element.velocity({ opacity: 0 }, { visibility: "hidden" });
Conversely, when display/visibility is set to a value other than "none"/"hidden", such as "block"/"visible", the corresponding value is set before the animation begins so that the element is visible throughout the duration of the animation.
(Further, if opacity is simultaneously animated, it'll be forced to a start value of 0. This is useful for fading an element back into view.)
Here, display is set to "block" before the element begins fading:
/* Set display to "block" then animate from opacity: 0. */ $element.velocity({ opacity: 1 }, { display: "block" });
Note: The display and visibility options are ignored when used with the Reverse command.
-
Command: Fade & Slide
Behavior
The fade and slide commands automatically set the targeted element's display property to show or hide the element (as appropriate). By default, when showing an element, display is set to the element's native type (divs are set to "block", spans are set to "inline", etc.). This can be overriden by passing a custom display value into the options object:
/* Set the element to a custom display value of "table". */ $element.velocity("fadeIn", { display: "table" });
fadeIn and fadeOut
To fade an element, pass in "fadeIn" or "fadeOut" as Velocity's first argument. The fade commands behaves identically to a standard Velocity call; they can take options and they can be queued.
$element [tab].velocity("fadeIn", { duration: 1500 }) [tab].velocity("fadeOut", { delay: 500, duration: 1500 });
Above, we fade an element in for 1500ms, pause for 500ms (delay: 500), then fade out for another 1500ms.
slideUp and slideDown
To animate an element's height to or from zero, pass in "slideDown" or "slideUp" as Velocity's first argument. Slide commands behave identically to standard Velocity calls; they take options and can be chained.
$element [tab].velocity("slideDown", { duration: 1500 }) [tab].velocity("slideUp", { delay: 500, duration: 1500 });
Above, we slide an element down into view over 1500ms, pause for 500ms (delay: 500), then slide up out of view for another 1500ms.
If you're looking for a highly performant mobile-first accordion powered by Velocity's slide functions, check out Bellows.
-
Command: Scroll
To scroll the browser to the top edge of an element, pass 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 it can be queued.
$element [tab].velocity("scroll", { duration: 1500, easing: "spring" }) [tab].velocity({ opacity: 1 });
Above, we scroll the browser to the top of edge of a div using a 1500ms duration and a "spring" easing. Then, once the element has scrolled into view, we fade it in.
To scroll toward an element that's inside a containing element with scrollbars, the scroll command uniquely takes an optional container option, which accepts either a jQuery object or a raw DOM element. The container element must have its CSS position property set to either relative, absolute, or fixed — static will not work:
/* Scroll $element into view of $("#container"). */ $element.velocity("scroll", { container: $("#container") });
Note that in both cases — whether scrolling is relative to the browser window or to a containing element — the scroll command is always called on the element that is being scrolled into view.
By default, scrolling occurs on the Y axis. Pass in the axis: "x" option to scroll horizontally instead:
/* Scroll the browser to the LEFT edge of the targeted div. */ $element.velocity("scroll", { axis: "x" });
Scroll also uniquely takes an offset option, specified in pixels, which offsets the target scroll position:
$element [tab]/* Then scroll to a position 250 pixels BELOW the div. */ [tab].velocity("scroll", { duration: 750, offset: 250 }) [tab]/* Scroll to a position 50 pixels ABOVE the div. */ [tab].velocity("scroll", { duration: 750, offset: -50 });
Alternatively, to scroll the entire browser window by an arbitrary amount (instead of to the edge of an element), simply target the html element and use a custom offset value. Optionally, additionally pass in mobileHA: false to avoid potential flickering issues on iOS:
/* Scroll the whole page to an arbitrary value. */ $("html").velocity("scroll", { offset: "750px", mobileHA: false });
-
Command: Stop
Overview
To immediately stop all current Velocity calls (including parallel animations called via queue: false) on an element, pass in "stop" as Velocity's first argument. The next Velocity call in the element's animation queue immediately starts.
If you're stopping a custom queue, pass the queue's name as the second parameter. Or, to only stop parallel animations (calls made with queue: false) but not the current default queue animation, pass false as the custom queue name.
$element.velocity("stop"); // Normal stop
$element.velocity("stop", "myQueue"); // Custom queue stop
When a call is stopped, its complete callback and display: none toggling are skipped.
Important: Note that a looped Velocity call is actually a series of Velocity calls chained together. Accordingly, to completely stop a looping animation, you must pass in the second parameter to clear the element's remaining calls. Similarly, in order to fully stop a UI pack effect (which can consist of multiple Velocity calls), you will need to clear the entirety of the element's pending animation queue. See Clearing the Animation Queue below for details on how to do so.
As a reference, a common pattern is to stop a call then animate back to its starting values using Velocity's reverse command:
/* Prior Velocity call. */ $element.velocity({ opacity: 0 });
/* Later, midway through the call... */ $element [tab]/* Stop animating opacity. */ [tab].velocity("stop") [tab]/* Animate opacity back to 1. */ [tab].velocity("reverse");
Clearing the Animation Queue
When a call is stopped, the next Velocity call in the element's queue chain fires immediately. Alternatively, you may pass in true (or the name of a custom queue) to clear all of the element's remaining queued calls. As with standard stop behavior, all parallel animations running on the element will also be stopped:
/* Prior Velocity calls. */ $element [tab].velocity({ width: 100 }, 1000) [tab].velocity({ height: 200 }, 1000);
/* Called immediately after. */ $element.velocity("stop", true);
Above, the initial { width: 100 } call will be instantly stopped, and the ensuing { height: 200 } will be removed and skipped entirely (it will never run).
Important: If you're clearing the remaining queue entries on a call that targeted more than one element, be sure that your stop command is applied to the full set of elements that the call initially targeted. Otherwise, some elements will have stuck queues and will ignore further Velocity calls until they are manually dequeued.
Stopping Multi-Element Calls
Because Velocity uses call-based tweening, when stop is called on an element, it is specifically the call responsible for that element's current animation that is stopped. Thus, if other elements were also targeted by that same call, they will also be stopped:
/* Prior Velocity call. */ $allElements.velocity({ opacity: 0 });
/* Stop the above call. */ $allElements.velocity("stop"); or /* Behaves like above since it's ending a multi-element call. */ $firstElement.velocity("stop");
If you want per-element stop control in a multi-element animation, perform the animation by calling Velocity once on each element.
-
Command: Finish
To prematurely jump to the end of an animation, use the finish command by passing in "finish" as Velocity's first argument.
$element.velocity("finish");
Whereas Velocity's stop command abruptly aborts an animation and leaves its animation properties at whatever values they had at the exact moment of stopping, finish applies the animation's desired final property values. Also, unlike stop, finish doesn't prevent a call's complete callback or display: none toggling from occurring. In short, think of the finish command as a means of immediately jumping to the last frame in an animation call.
As with stop, calling finish will also affect all currently-active parallel animations (animations called with queue: false). Further, passing in a second argument of false to the finish command has the same effect as passing this argument to the stop command: Only parallel animations are targeted for finishing. Finally, passing in a second argument of true to the finish command also has the same effect as passing this argument to the stop command: In addition to the command's default behavior (stopping the currently-queued call plus all parallel animations), remaining calls on the default queue will also be removed from the queue. Note, however, that these calls aren't immediately run before being removed; the remaining queued calls' animation effects will not take place at all.
-
Command: Reverse
To animate an element back to the values prior to its last Velocity call, pass in "reverse" as Velocity's first argument.
Reverse defaults to the options (duration, easing, etc.) used in the element's previous Velocity call. However, this can be overridden by passing in a new options object:
$element.velocity("reverse"); or $element.velocity("reverse", { duration: 2000 });
The previous call's callback options (begin and complete) are ignored by reverse; reverse does not re-fire callbacks.
Note: The reverse command only applies to the default effects queue; reverse cannot be used with custom queues or parallel queueing (queue: false).
-
Feature: Transforms
Overview
The CSS transform property allows you to perform translation, scaling, and rotation in 2D or 3D space. Learn more at MDN.
To achieve parity with CSS, Velocity uses the translateX and translateY property names for transform translations, not X and Y.
/* Translate to the right and rotate clockwise. */ $element.velocity({ [tab]translateX: "200px", [tab]rotateZ: "45deg" });
Since Velocity only animates one numeric value per CSS property, an axis must be declared with a transform property. For example, scale cannot be animated to "1.5, 2", but scaleX() and scaleY() can be simultaneously animated to those values to achieve the same effect. (Refer to the CSS Support dropdown for Velocity's full transform property support.)
Note that Velocity's performance optimizations have the byproduct of ignoring outside changes to transform values (including initial values as defined in your stylesheets, but this is remedied via Forcefeeding). (You can manually set transform values within Velocity by using the Hook function.)
Details
All browsers automatically trigger hardware acceleration (HA) when 3D transform properties (translateZ and rotateX/Y) are being animated. The advantages of HA include increased smoothness, while the disadvantages include blurry text and memory consumption. If you want to also force HA for 2D transforms in order to benefit from the increased performance it can provide (at the expense of possible text blurriness), then trigger HA by animating a 3D transform property to a bogus value (such as 0) during your animation:
/* Translate to the right and rotate clockwise. */ $element.velocity({ [tab]translateZ: 0, // Force HA by animating a 3D property [tab]translateX: "200px", [tab]rotateZ: "45deg" });
(This section applies to desktop browsers only — by default, Velocity automatically turns HA on for all animations on mobile. See mobileHA for more information.)
Browser support: Remember that 3D transforms are not supported below IE 10 and below Android 3.0, and that even 2D transforms aren't supported below IE 9. Also, remember that a perspective must be set on a parent element for 3D transforms to take effect. See MDN's transform guide to learn more.
-
Feature: Colors
Velocity supports color animation for the following properties: color, backgroundColor, borderColor, and outlineColor.
You can pass a color property a hex string (rgb, hsla strings, and color keywords are not supported), or you can animate the individual RGB component values of a color property: The color components are Red, Green, Blue, and Alpha, and they range from from 0 to 255. (They may also be passed a percent value.) The fourth component, Alpha (the same thing as opacity), ranges from 0 to 1.
$element.velocity({ [tab]/* Animate a color property to a hex value of red... */ [tab]backgroundColor: "#ff0000", [tab]/* ... with a 50% opacity. */ [tab]backgroundColorAlpha: 0.5, [tab]/* Animate the red RGB component to 50% (0.5 * 255). */ [tab]colorRed: "50%", [tab]/* Concurrently animate to a stronger blue. */ [tab]colorBlue: "+=50", [tab]/* Fade the text down to 85% opacity. */ [tab]colorAlpha: 0.85 });
In IE 9 and below, where RGBA is not supported, Velocity reverts to plain RGB by ignoring the Alpha component.
-
Feature: SVG
Velocity contains full support for SVG element animation, including the animation of SVG-specific properties such as x, rx, stroke-width, and so on. (In general, Velocity can animate any property that takes a single numeric value.) Further, Velocity supports color animation for SVG's fill, stroke, and stopColor properties.
There are two caveats with SVG element animation: First, not all CSS properties can be applied to SVG elements. (See the dropdown below for a list of supported properties.) Second, while SVG properties can take the px and % units, they cannot take the em and rem units. To learn more about working with SVG, refer to this article.
Note that — as listed in the dropdown above — only 2D SVG transform properties work in IE and Android devices that are not running Chrome. (All other browsers have full 3D support.) Further, note the whitelist of supported unit types for each property in the dropdown list.
Here are some sample SVG properties:
$svgRectangle.velocity({ [tab]/* Coordinate animation works. */ [tab]x: 200, [tab]r: 25, [tab]/* 2D transforms work. */ [tab]translateX: "200px", [tab]/* 3D transforms work in non-IE browsers. */ [tab]translateZ: "200px", [tab]/* "Fill" color animation works. */ [tab]fill: "#ff0000", [tab]strokeRed: 255, [tab]strokeGreen: 0, [tab]strokeBlue: 0, [tab]/* Some standard CSS properties work. */ [tab]opacity: 1, [tab]width: "50%" });
Note: If you set a viewbox attribute while also setting width/height attributes on an SVG container element, the width and height values must match the viewbox's width/height, otherwise animating with the % unit can result in incorrect animations.
Browser support: SVG elements are not supported below IE9 or below Android 3.0.
-
Feature: Hook
Hooks are the subvalues of multi-value CSS properties. For example, the textShadow CSS property takes a multi-value form of "0px 0px 0px black". Velocity allows you to individually animate each of these subvalues, e.g. textShadowX, textShadowY, and textShadowBlur:
$element.velocity({ textShadowBlur: "10px" });
Similarly, Velocity allows you to animate the subvalues of boxShadow, clip, and other multi-value properties. Refer to the CSS Property Support pane for the full list of Velocity's hooks.
Since it's not possible to individually set these hook values via jQuery's $.css(), Velocity provides a hook() helper function. It features the same API as $.css(), with the modification that it takes an element as its first argument (either a raw DOM node or a jQuery object): $.Velocity.hook(element, property [, value])l:
Set a hook value:
$.Velocity.hook($element, "translateX", "500px"); // Must provide unit type
$.Velocity.hook(elementNode, "textShadowBlur", "10px"); // Must provide unit type
Get a hook value:
$.Velocity.hook($element, "translateX");
$.Velocity.hook(elementNode, "textShadowBlur");
Note: When using the hook function, you must provide a unit type (e.g. px, deg, etc.) if the CSS property can accept one.
-
Feature: Promises
If you're new to promises, read this article.
A Velocity call automatically returns a promise object when both A) the utility function is used and B) promise support is detected in the browser (see Browser Support below for further details). Conversely, promises are never returned when using jQuery's object syntax (e.g. $element.velocity(...)).
/* Using Velocity's utility function... */ $.Velocity.animate(element, { opacity: 0.5 }) [tab]/* Callback to fire once the animation is complete. */ [tab].then(function(elements) { console.log("Resolved."); }) [tab]/* Callback to fire if an error occurs. */ [tab].catch(function(error) { console.log("Rejected."); });
The returned promise is resolved when the call's animation completes, regardless of whether it completed on its own or prematurely due to the user calling $element.velocity("stop"[, true]). The resolve function is passed the entire raw DOM (not jQuery) element array as both its context and its first argument. To access these elements individually, you must iterate over the array using jQuery's $.each() or JavaScript's native .forEach().
Conversely, the promise is rejected when an invalid first argument is passed into a Velocity call (e.g. an empty properties object or a Velocity command that does not exist). The reject callback is passed the triggered error object.
Promises also work with effects from the UI pack (including custom effects). As usual, however, ensure that you're calling the UI pack effect using Velocity's utility function. Further, ensure you're using the latest version of the UI pack, since promise support was added only recently.
Browser support: Only Chrome desktop and Firefox desktop have native support for promises. For all other browsers, you must install a third-party promises library, such as Bluebird or When's ES6 Promises shim. (Do not use Q, since it doesn't automatically install itself like ES6 promises do.) When using Bluebird or When, ensure that the promise library is loaded before Velocity. Both Bluebird and When work back to Android 2.3 and IE8.
-
Feature: Mock
When performing UI testing, you can set $.Velocity.mock = true; to force all Velocity animations to run with 0ms duration and 0ms delay. (In essence, values are fully applied on the next animation tick.) This is incredibly helpful when performing repetitious UI testing for which testing end values is more important than testing animation tweening.
Alternatively, you can also set $.Velocity.mock to an arbitrary multiplier to speed up or slow down all animations on the page:
/* Slow down all animations by a factor of 10. */ $.Velocity.mock = 10;
Slowing down animations in this way is useful when you're trying to fine tune the timing of multi-element animation sequences.
-
Feature: Utility Function
Instead of using jQuery's plugin syntax to target jQuery objects, you can use Velocity's utility function to target raw DOM elements:
/* Standard multi-argument syntax. */ var divs = document.getElementsByTagName("div"); $.Velocity(divs, { opacity: 0 }, { duration: 1500 });
/* Alternative single-argument syntax (ideal for CoffeeScript). e stands for elements, p for properties, and o for options: */ var divs = document.getElementsByTagName("div"); $.Velocity({ e: divs, p: { opacity: 0 }, o: { duration: 1500 });
The syntax is identical to Velocity's standard syntax, except for all of the arguments are shifted one place to the right so that you can pass in elements at position zero.
Using the utility function is useful when you're generating elements in real-time and cannot afford the overhead of jQuery object creation, which triggers DOM queries.
Below is an example of the utility function. Click on the JS tab to see the corresponding JavaScript:
-
Advanced: Value Functions
Property values can be passed functions. These functions are called once per element — immediately before the element begins animating. Therefore, when looping/reversing, the functions are not repeatedly re-called.
The value returned by the function is used as the property value:
$element.velocity({ [tab]opacity: function() { return Math.random() } });
Value functions are passed the iterating element as their context, plus a first argument containing the element's index within the set and a second argument containing the total length of the set. By using these values, visual offseting can be achieved:
$element.velocity({ [tab]translateX: function(i, total) { [tab][tab]/* Generate translateX's end value. */ [tab][tab]return i * 10; [tab]} });
In addition to helping contain animation logic within Velocity, value functions are the most performant way of differentiating properties amongst a set of elements — as opposed to pre-iterating through them and calling Velocity once for each, which forgoes Velocity's element set optimization.
-
Advanced: Forcefeeding
Traditionally, animation engines query the DOM to determine the initial value for each property being animated. Velocity is the originator of an alternative technique entitled forcefeeding, in which users explicitly define start values themselves so that DOM querying can be avoided — eliminating layout thrashing altogether.
Forcefed start values are passed as a second or third item in an array that takes the place of a property's value. (As described in the Easing pane, the second item can optionally be a per-property easing).
$element.velocity({ [tab]/* Two-item array format. */ [tab]translateX: [ 500, 0 ], [tab]/* Three-item array format with a per-property easing. */ [tab]opacity: [ 0, "easeInSine", 1 ] });
Above, we're passing translateX a start value of 0 since we know the element has yet to be translated (perhaps the page has just loaded). Next, we also know that the element's opacity is currently 1 because that's opacity's default value and we haven't modified the element yet. With both properties, we're forcefeeding in what we know (or want) the original animation values to be.
Like standard property values, forcefed start values also accept value functions. (You can take advantage of this feature to seed an element set differentiated start values. See Velocity's 3D demo codecast for an example of this.)
Be sure to forcefeed only at the start of an animation, not between chained animations (where Velocity already does value caching internally):
$element [tab]/* Optionally forcefeed here. */ [tab].velocity({ translateX: [ 500, 0 ] }) [tab]/* Do not forcefeed here; 500 is internally cached. */ [tab].velocity({ translateX: 1000 });
Forcefeeding is invaluable in high-stress situations — in which heavy DOM querying can greatly impact framerate. However, in most low-stress UI animation, forcefeeding is an unnecessary optimization.
Note: Forcefeeding a hook's subproperty will default that hook's non-animated subproperties to their zero-values.
-
Feature: Sequences
Sequence registration is deprecated. See the Custom Effects section of Velocity's UI Pack (below) for a better solution. -
Plugins: UI Pack
Overview
At only 3Kb zipped, the UI pack is a must-have for improving your animation workflow. It exposes two functions: $.Velocity.RegisterEffect() and $.Velocity.RunSequence(). The former allows you to combine multiple Velocity calls into a a single effect that you can reference by name. The latter helps make nested animation sequences much more manageable.
Additionally, the UI pack includes a couple dozen pre-registered effects. Refer to the Effects: Pre-Registered section below.
Download the pack (or visit GitHub) then load it after Velocity. There's also a plugin for Angular users. The UI pack does not require jQuery to be loaded on your page.
The UI pack is covered thoroughly in the Velocity.js book.
This feature was added recently. Ensure you're using the latest version of the UI pack.
Sequence running is the UI pack's solution to avoiding messy, nested animation code. For example, without the UI pack, this is the standard approach to consecutively animating separate elements:
$element1.velocity({ translateX: 100 }, 1000, function() { [tab]$element2.velocity({ translateX: 200 }, 1000, function() { [tab][tab]$element3.velocity({ translateX: 300 }, 1000); [tab]}); });
To make matters worse, if the above code were to define its animation options using Velocity's options object syntax — as opposed to the comma-separated syntax currently demonstrated — it would quickly become a nest of unmanageable code. Additional issues with this nesting approach include having your code expanding horizontally (making it difficult to browse), and the inability to easily re-arrange the order of calls in your sequence.
With the UI pack's Sequence running feature, you simply use Velocity's utility function and single-object arguments syntax to create an array of Velocity call objects that make up your animation sequence. e stands for elements, p for properties, and o for options:
var mySequence = [ [tab]{ e: $element1, p: { translateX: 100 }, o: { duration: 1000 } }, [tab]{ e: $element2, p: { translateX: 200 }, o: { duration: 1000 } }, [tab]{ e: $element3, p: { translateX: 300 }, o: { duration: 1000 } } ];
$.Velocity.RunSequence(mySequence);
You then pass the sequence array into $.Velocity.RunSequence(), which will consecutively fire each call within the sequence.
Sequence running also exposes a special sequenceQueue option which, when set to false, forces the associated call to run in parallel with the call that came before it:
var mySequence = [ [tab]{ e: $element1, p: { translateX: 100 }, o: { duration: 1000 } }, [tab]/* The call below will run at the same time as the first call. */ [tab]{ e: $element2, p: { translateX: 200 }, o: { duration: 1000, sequenceQueue: false }, [tab]/* As normal, the call below will run once the second call is complete. */ [tab]{ e: $element3, p: { translateX: 300 }, o: { duration: 1000 } ];
$.Velocity.RunSequence(mySequence);
Effects: Pre-Registered
The UI pack includes a couple dozen pre-registered effects for you to use out of the box. Use cases for these effects include drawing the user's attention to an element, dynamically loading content, and displaying modals. Refer to the tutorial for a full overview.
To trigger an effect, simply pass its name as Velocity's first argument (instead of a properties map), e.g.
$elements.velocity("callout.bounce");
UI pack effects do not accept the loop, easing, or progress options. Further, they cannot be used with parallel queueing (ie. queue: false).Note that display: inline elements cannot take the CSS transform property (which most of the UI pack effects use). Accordingly, the UI pack automatically switches any display: inline elements that it animates to display: inline-block.
Below is a listing of all pre-registered effects:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Effects: Behavior
- UI pack effects behave like normal Velocity calls; they can be chained and can take options.
- Elements automatically switch to display: block/inline when transitioning in, and back to display: none after transitioning out. (To prevent this behavior, pass display: null as an option into the UI Pack call.)
- Support the special stagger, drag, and backwards options. (Refer to the next section.)
- Browser support: Below IE10 and Android 3.0, the flip and perspective transitions gracefully fall back to simply fading in and out. In IE8, all transitions gracefully fall back to just fading in and out, and callouts (except for callout.flash) have no effect.
There are three options that work only with UI pack effects — but not with traditional Velocity calls. They are passed into a UI pack call as standard Velocity call options:
- Stagger: Specify the stagger option in ms to successively delay the animation of each element in a set by the targeted amount. You can also pass in a value function to define your own stagger falloffs.
- Drag: Set the drag option to true to successively increase the animation duration of each element in a set. The last element will animate with a duration equal to the sequence's original value, whereas the elements before the last will have their duration values gradually approach the original value. The end result is a cross-element easing effect.
- Backwards: Set the backwards option to true to animate starting with the last element in a set. This option is ideal for use with an effect that transitions elements out of view since the backwards option mirrors the behavior of elements transitioning into view (which, by default, animate in the forwards direction — from the first element to the last).
Refer to the tutorial for a step-by-step overview of using these options.
This feature was added recently. Ensure you're using the latest version of the UI pack.
The UI pack allows you to register custom effects, which also accept the special stagger, drag, and backwards options. Once registered, an effect is called by passing its name as Velocity's first parameter: $element.velocity("name").
Benefits of custom effects include separating UI animation design from UI interaction logic, naming animations for better code organization, and packaging animations for re-use across projects and for sharing with others.
A custom UI pack effect is registered with the following syntax:
$.Velocity.RegisterEffect(name, { [tab]defaultDuration: duration, [tab]calls: [ [tab][tab][ { property: value }, durationPercentage, { options } ], [tab][tab][ { property: value }, durationPercentage, { options } ] [tab]], [tab]reset: { property: value, property: value } });
In the above template, we pass an optional defaultDuration property, which specifies the duration to use for the full effect if one is not passed into the triggering Velocity call, e.g. $element.velocity("name"). Like a value function, defaultDuration also accepts a function to be run at an animation's start. This function is called once per UI pack call (regardless of how many elements are passed into the call), and is passed the raw DOM element set as both its context and its first argument.
Next is the array of Velocity calls to be triggered (in order). Each call takes a standard properties map, followed by the percentage (as a decimal) of the effect's total animation duration that the call should consume (defaults to 1 if unspecified), followed by an optional animation options object. This options object only accepts Velocity's easing and delay options.
Lastly, you may optionally pass in a reset property map (using standard Velocity properties and values), which immediately applies the specified properties upon completion of the effect. This is useful for when you're, say, scaling an element down to 0 (out of view) and want to return the element to scale:1 once the element is hidden so that it’s normally scaled when it’s made visible again sometime in the future.
Sample effect registrations:
Callout:
$.Velocity.RegisterEffect("callout.pulse", { [tab]defaultDuration: 900, [tab]calls: [ [tab][tab][ { scaleX: 1.1 }, 0.50 ], [tab][tab][ { scaleX: 1 }, 0.50 ] [tab]] });
$element.velocity("callout.pulse");
Transition:
/* Registration */ $.Velocity [tab].RegisterEffect("transition.flipXIn", { [tab][tab]defaultDuration: 700, [tab][tab]calls: [ [tab][tab][tab][ { opacity: 1, rotateY: [ 0, -55 ] } ] [tab][tab]] [tab]}); [tab].RegisterEffect("transition.flipXOut", { [tab][tab]defaultDuration: 700, [tab][tab]calls: [ [tab][tab][tab][ { opacity: 0, rotateY: 55 } ] [tab][tab]], [tab][tab]reset: { rotateY: 0 } [tab]});
/* Usage */ $element [tab].velocity("transition.flipXIn") [tab].velocity("transition.flipXOut", { delay: 1000 });
(For additional examples, browse the UI pack's source.)
Note that, if your effects' names end with In or Out, Velocity will automatically set the display option to "none" or the element’s default type for you. In other words, elements are set to display: block Before beginning an “In” transition or display: none after completing an Out transition.
/* Bypass the UI pack's automatic display setting. */ $element.velocity("transition.flipXIn", { display: null });
Below is an example of a custom UI pack effect registration. Click on the JS tab:
-
Plugins: VMD
Overview
Watch the video for a full overview.
Velocity Motion Designer (VMD) is a bookmarklet that you load onto a page in order to create animations in real-time. Once you're done creating, you can export your work into 1-for-1 Velocity code. (The outputted code is also compatible with jQuery — just skip the delay parameter and only use CSS properties that jQuery can animate.)
VMD saves countless hours of development time by preventing constant IDE ↔ browser switching and repeated UI state retriggering. Further, it streamlines the designer ↔ developer workflow by allowing them to work alongside one another in real-time.
Documentation
VMD's documentation is outputted to the browser console upon script load.
Usage
Note: VMD includes jQuery, Velocity, and Velocity's UI pack. You do not need to load these libraries beforehand.
There are three different ways to load VMD:
- Drag this link into your bookmarks bar to create a bookmarklet: VMD. Thereafter, simply click the bookmarklet to activate VMD on the page you're browsing.
-
Or, include this at the end of your page's <body> element:
<script src="https://julian.com/research/velocity/vmd.min.js"></script>
-
Or, open up your browser's developer tools and paste this into your console:
(function(d) { var vmd=d.createElement("script"); vmd.src="https://julian.com/research/velocity/vmd.min.js"; d.body.appendChild(vmd); })(document);
-
Plugins: Ember & Misc.
Ember UI is a UI component library with motion design powered by Velocity.
Liquid Fire provides comprehensive Velocity-powered animation.
Ember Velocity Mixin is an alternative to Liquid Fire.
Tweene is a timeline manipulation library that works on top of Velocity.
Bellows is a mobile-first accordion widget that that uses Velocity for its motion.
ScrollMagic is standalone scroll animation library that works with Velocity.