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.
Libscore
lists some of Velocity's biggest users.
Click here
to see a comparison between jQuery and Velocity animating a dialog box. You can
view the code
that powers this comparison.
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.
Articles
If you're experiencing an issue, first ensure you're using the latest version of Velocity. You can grab it from
GitHub
.
Also, check the
FAQ
to see if your question has already been answered.
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.
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 becomes
Velocity
.
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 });
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"); });
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.
Values
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.
[tab]/* Animate the width property. */
[tab].velocity({ width: 75 })
[tab]/* Then, when finished, animate the height property. */
[tab].velocity({ height: 0 });
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");
$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;
/* 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
.
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
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); }
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.
[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]}
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 });
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.)
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
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.
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
.
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 });
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 });
[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);
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 });
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.
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");
$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).
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.
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.
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.
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.
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.
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.
/* 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:
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.
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.
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
.
Sequence Running
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 } }
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 }
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.
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.
Effects: Registration
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]]
[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]});
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>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
I agree. I disagree.